From b29356569fc98251ee0c7e4072da74703099ee95 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Wed, 2 Oct 2024 11:07:49 -0400 Subject: [PATCH 01/89] fix issues #1159, #670 --- cime_config/testdefs/testlist_cam.xml | 14 +-- .../testmods_dirs/cam/dae/shell_commands | 6 -- .../testmods_dirs/cam/dae/user_nl_cam | 4 - .../testmods_dirs/cam/dae/user_nl_cpl | 2 - doc/ChangeLog | 70 ++++++++++++++ test/system/da_cam_no_data_mod.sh | 95 ------------------- 6 files changed, 73 insertions(+), 118 deletions(-) delete mode 100644 cime_config/testdefs/testmods_dirs/cam/dae/shell_commands delete mode 100644 cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam delete mode 100644 cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl delete mode 100755 test/system/da_cam_no_data_mod.sh diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index b2c62fd5e7..20e283f0c8 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -57,7 +57,7 @@ - + @@ -67,7 +67,7 @@ - + @@ -2031,15 +2031,7 @@ - - - - - - - - - + diff --git a/cime_config/testdefs/testmods_dirs/cam/dae/shell_commands b/cime_config/testdefs/testmods_dirs/cam/dae/shell_commands deleted file mode 100644 index f091402c1d..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/dae/shell_commands +++ /dev/null @@ -1,6 +0,0 @@ -# Test CAM post-Data Assimilation handling -SRCROOT="`./xmlquery --value COMP_ROOT_DIR_ATM`" -DAFILE="${SRCROOT}/test/system/da_cam_no_data_mod.sh" -./xmlchange DATA_ASSIMILATION_SCRIPT=${DAFILE} -# Turn off any use case -./xmlchange CAM_NML_USE_CASE="UNSET" diff --git a/cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam deleted file mode 100644 index f837808297..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam +++ /dev/null @@ -1,4 +0,0 @@ -! CAM history files have different names when DA is active so turn them off -nhtfrq = 0,-10000,-10000,-10000,-10000,-10000 -fexcl1 = 'OMEGA','OMEGAT','PHIS','PS','PSL','QRS','T','U','UU','V','VT','VU','VV','Z3' -fexcl2 = 'T','U','V' diff --git a/cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl b/cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl deleted file mode 100644 index 398535cf65..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl +++ /dev/null @@ -1,2 +0,0 @@ -reprosum_diffmax=1.0e-14 -reprosum_recompute=.true. diff --git a/doc/ChangeLog b/doc/ChangeLog index c576afc24e..dd4edfeedb 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,73 @@ +=============================================================== + +Tag name: +Originator(s): eaton +Date: +One-line Summary: fix issues #1159, #670 +Github PR URL: + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + +Issue #1159 - Prealpha tests exceeding wallclock + - increased time limit to 20 minutes for these prealpha tests: + ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s + ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s + +Issue #670 - DAE test broken + . ChangeLog indicates that this test has never worked since it was added + in cam6_2_046 (2020-09-01). Test removed. + + + + +Describe any changes made to build system: + +Describe any changes made to the namelist: + +List any changes to the defaults for the boundary datasets: + +Describe any substantial timing or memory changes: + +Code reviewed by: + +List all files eliminated: + +cime_config/testdefs/testmods_dirs/cam/dae/shell_commands +cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam +cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl +test/system/da_cam_no_data_mod.sh +. DAE test removed + +List all files added and what they do: + +List all existing files that have been modified, and describe the changes: + +cime_config/testdefs/testlist_cam.xml +. increase time limit to 20 minutes for these prealpha tests: + ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s + ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s +. remove non-working DAE test + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers: + +=============================================================== + Tag name: cam6_4_038 Originator(s): lizziel Date: 1 Oct 2024 diff --git a/test/system/da_cam_no_data_mod.sh b/test/system/da_cam_no_data_mod.sh deleted file mode 100755 index ef5313d4cc..0000000000 --- a/test/system/da_cam_no_data_mod.sh +++ /dev/null @@ -1,95 +0,0 @@ -#! /bin/bash - -############################################################################## -### -### A stub data assimilation script that prints out information but makes -### no modifications to model data. -### Script checks for proper pre and post data assimilation output -### Tests using this script should be BFB with a non-data assimilation run -### -############################################################################## - -errcode=0 -if [ $# -ne 2 ]; then - echo "ERROR: Wrong number of arguments, $# (should be 2)" - errcode=$(( errcode + 1 )) -else - caseroot=$1 - cycle=$2 - echo "caseroot: ${caseroot}" - echo "cycle: ${cycle}" - cd ${caseroot} - res=$? - if [ $res -ne 0 ]; then - echo "ERROR: Unable to cd to caseroot, ${caseroot}" - errcode=$(( errcode + 1 )) - else - ./xmlchange DATA_ASSIMILATION_ATM=TRUE - res=$? - if [ $res -ne 0 ]; then - echo "ERROR: Unable to change DATA_ASSIMILATION_ATM to TRUE" - errcode=$(( errcode + 1 )) - fi - rundir="`./xmlquery --value RUNDIR`" - ninst=`./xmlquery --value NINST_ATM` - if [ -n "${rundir}" -a -d "${rundir}" ]; then - cd ${rundir} - res=$? - if [ $res -ne 0 ]; then - echo "ERROR: Unable to cd to rundir, ${rundir}" - errcode=$(( errcode + 1 )) - else - # Check the latest log file for a resume signal - if [ $ninst -eq 1 ]; then - lfiles="`ls -t atm.log.* 2> /dev/null | head -1`" - else - # Multi-instance, look for wav_nnnn.log* - for inst in `seq 1 $ninst`; do - ifilename="`printf "atm_%04d.log.*" $inst`" - ifile="`ls -t ${ifilename} 2> /dev/null | head -1`" - if [ -z "${ifile}" ]; then - echo "No log files for instance $ninst found" - errcode=$(( errcode + 1 )) - elif [ -z "${lfiles}" ]; then - lfiles="${ifile}" - else - lfiles="${lfiles} ${ifile}" - fi - done - fi - if [ -z "${lfiles}" ]; then - echo "ERROR: Unable to find atm log file in `pwd -P`" - errcode=$(( errcode + 1 )) - else - for atmfile in ${lfiles}; do - dasig="`zgrep '^[ ]*DART run using CAM initial mode$' ${atmfile} 2> /dev/null`" - initsig="`zgrep '^[ ]*Initial run$' ${atmfile} 2> /dev/null`" - if [ $cycle -gt 0 ]; then - if [ -n "${dasig}" ]; then - echo "Post-DA resume signal found for cycle ${cycle}" - else - echo "No post-DA resume signal for cycle ${cycle}" - fi - elif [ -n "${dasig}" ]; then - echo "Bad Post-DA resume signal found for cycle ${cycle}" - fi - if [ $cycle -eq 0 ]; then - if [ -n "${initsig}" ]; then - echo "Initial run signal found for cycle ${cycle}" - else - echo "No initial run signal found for cycle ${cycle}" - fi - elif [ -n "${initsig}" ]; then - echo "Bad initial run signal found for cycle ${cycle}" - fi - done - fi - fi - else - echo "ERROR: RUNDIR (${rundir}) is not a valid directory" - errcode=$(( errcode + 1 )) - fi - fi -fi - -exit $errcode From 37430e150d1d820e993fa7f306a20c4221fa7c2e Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Fri, 11 Oct 2024 22:28:41 -0600 Subject: [PATCH 02/89] Manually merging in changes from ew-develop --- src/physics/cam/clubb_intr.F90 | 37 +++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 9bbf211fba..6b22d53953 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2602,10 +2602,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! - call t_startf("clubb_tend_cam") nlev = pver + 1 - top_lev + call t_startf('clubb_tend_cam:NAR') rtp2_zt_out = 0._r8 thl2_zt_out = 0._r8 wp2_zt_out = 0._r8 @@ -2781,6 +2781,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call grid_size(state1, grid_dx, grid_dy) + call t_stopf('clubb_tend_cam:NAR') + if (clubb_do_icesuper) then ! -------------------------------------- ! @@ -2801,11 +2803,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & qitend(:ncol,:)=0._r8 initend(:ncol,:)=0._r8 + call t_startf('clubb_tend_cam:ice_macro_tend') call ice_macro_tend(naai(1:ncol,top_lev:pver), state1%t(1:ncol,top_lev:pver), & state1%pmid(1:ncol,top_lev:pver), state1%q(1:ncol,top_lev:pver,1), & state1%q(1:ncol,top_lev:pver,ixcldice), state1%q(1:ncol,top_lev:pver,ixnumice), & latsub, hdtime, stend(1:ncol,top_lev:pver), qvtend(1:ncol,top_lev:pver), & qitend(1:ncol,top_lev:pver), initend(1:ncol,top_lev:pver), ncol*(pver-top_lev+1)) + call t_stopf('clubb_tend_cam:ice_macro_tend') ! update local copy of state with the tendencies ptend_loc%q(:ncol,top_lev:pver,1)=qvtend(:ncol,top_lev:pver) @@ -2827,6 +2831,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'NITENDICE', initend, pcols, lchnk ) endif + call t_startf('clubb_tend_cam:NAR') ! Determine CLUBB time step and make it sub-step friendly @@ -2991,7 +2996,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & mf_qtflx_output(:,:) = 0._r8 end if - call t_startf("clubb_tend_cam_i_loop") ! Determine Coriolis force at given latitude. This is never used ! when CLUBB is implemented in a host model, therefore just set @@ -3234,7 +3238,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert = 0.0_r8 vpwp_sfc_pert = 0.0_r8 + call t_stopf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core do k=1,nlev+1 do i=1,ncol @@ -3448,6 +3454,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (macmic_it==1) vpwp_clubb_gw_mc(:ncol,:) = 0._r8 if (macmic_it==1) thlp2_clubb_gw_mc(:ncol,:) = 0._r8 if (macmic_it==1) wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + call t_stopf('clubb_tend_cam:flip-index') do t=1,nadv ! do needed number of "sub" timesteps for each CAM step @@ -3461,6 +3468,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !###################### CALL MF DIAGNOSTIC PLUMES ###################### !####################################################################### if (do_clubb_mf) then + call t_startf('clubb_tend_cam:do_clubb_mf') do k=2,pverp do i=1, ncol @@ -3511,10 +3519,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ((rho_ds_zm(i,k) * mf_thlflx(i,k)) - (rho_ds_zm(i,k-1) * mf_thlflx(i,k-1))) end do end do + call t_stopf('clubb_tend_cam:do_clubb_mf') end if ! Advance CLUBB CORE one timestep in the future + call t_startf('clubb_tend_cam:advance_clubb_core_api') call advance_clubb_core_api( gr, pverp+1-top_lev, ncol, & l_implemented, dtime, fcor, sfc_elevation, & hydromet_dim, & @@ -3559,6 +3569,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & cloudy_updraft_frac_out, cloudy_downdraft_frac_out, & rcm_in_layer_out, cloud_cover_out, invrs_tau_zm_out ) + call t_stopf('clubb_tend_cam:advance_clubb_core_api') ! Note that CLUBB does not produce an error code specific to any column, and ! one value only for the entire chunk @@ -3582,12 +3593,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + call t_startf('clubb_tend_cam:update_xp2_mc_api') call update_xp2_mc_api( gr, nlev+1, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & rtp2_mc_out, thlp2_mc_out, & wprtp_mc_out, wpthlp_mc_out, & rtpthlp_mc_out) + call t_stopf('clubb_tend_cam:update_xp2_mc_api') do k=1,nlev+1 do i=1,ncol @@ -3605,6 +3618,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (do_cldcool) then + call t_startf('clubb_tend_cam:do_cldcool') rcm_out_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, rcm_inout ) qrl_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, qrl_clubb ) @@ -3619,19 +3633,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & thlp2_in(i,:) = thlp2_in(i,:) + thlp2_rad_out(i,:) * dtime thlp2_in(i,:) = max(thl_tol**2,thlp2_in(i,:)) end do + call t_stopf('clubb_tend_cam:do_cldcool') end if ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (stats_metadata%l_stats) then + call t_startf('clubb_tend_cam:stats_end_timestep_clubb') do i=1, ncol call stats_end_timestep_clubb(i, stats_zt(i), stats_zm(i), stats_rad_zt(i), stats_rad_zm(i), stats_sfc(i), & out_zt, out_zm, out_radzt, out_radzm, out_sfc) end do + call t_stopf('clubb_tend_cam:stats_end_timestep_clubb') end if enddo ! end time loop + call t_startf('clubb_tend_cam:NAR') if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -3657,12 +3675,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if + call t_stopf('clubb_tend_cam:NAR') ! Convert RTP2 and THLP2 to thermo grid for output + call t_startf('clubb_tend_cam:NAR') rtp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) thl2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) wp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) + call t_stopf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:flip-index') ! Arrays need to be "flipped" to CAM grid do k=1, nlev+1 do i=1, ncol @@ -3722,6 +3744,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + call t_stopf('clubb_tend_cam:flip-index') + call t_startf('clubb_tend_cam:NAR') ! Accumulate vars through macmic subcycle upwp_clubb_gw_mc(:ncol,:) = upwp_clubb_gw_mc(:ncol,:) + upwp(:ncol,:) @@ -4021,7 +4045,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end do - call t_stopf("clubb_tend_cam_i_loop") call outfld('KVH_CLUBB', khzm, pcols, lchnk) @@ -4068,9 +4091,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! then advances it's predictive equations second, this can lead to ! RHliq > 1 directly before microphysics is called. Therefore, we use ! ice_macro_tend to enforce RHliq <= 1 everywhere before microphysics is called. + call t_stopf('clubb_tend_cam:NAR') if (clubb_do_liqsupersat) then + call t_startf('clubb_cam_tend:do_liqsupersat') ! -------------------------------------- ! ! Ice Saturation Adjustment Computation ! ! -------------------------------------- ! @@ -4122,7 +4147,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end where call outfld( 'FQTENDICE', fqtend, pcols, lchnk ) + call t_stopf('clubb_cam_tend:do_liqsupersat') end if + call t_startf('clubb_tend_cam:NAR') ! ------------------------------------------------------------ ! ! The rest of the code deals with diagnosing variables ! @@ -4547,8 +4574,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo endif - - call t_stopf("clubb_tend_cam") + call t_stopf('clubb_tend_cam:NAR') + return #endif From 94275055d5275b8ea2f1d6a8ea06242992dd3b66 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Sat, 12 Oct 2024 10:40:58 -0600 Subject: [PATCH 03/89] Adding acc data statement outside substepping loop and preventing some options from running when compiled with OpenACC --- src/physics/cam/clubb_intr.F90 | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 6b22d53953..4b30e503ac 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2598,6 +2598,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & #ifdef CLUBB_SGS +#ifdef _OPENACC + ! These options have not been GPUized + if ( do_clubb_mf ) call endrun(subr//': do_clubb_mf=.true. not available when compiling with OpenACC') + if ( do_rainturb ) call endrun(subr//': do_rainturb=.true. not available when compiling with OpenACC') + if ( do_cldcool ) call endrun(subr//': do_cldcool=.true. not available when compiling with OpenACC') +#endif + !-----------------------------------------------------------------------------------! ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! @@ -3456,6 +3463,94 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (macmic_it==1) wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 call t_stopf('clubb_tend_cam:flip-index') + + call t_startf('clubb_tend_cam:acc_copyin') + !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & + !$acc gr%weights_zt2zm, gr%weights_zm2zt, & + !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & + !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & + !$acc nu_vert_res_dep%nu6, & + !$acc sclr_idx, clubb_params, & + !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & + !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, & + !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & + !$acc vm_ref, ug, vg, grid_dx, grid_dy, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk) ) & + !$acc copy( um_in, upwp_in, vm_in, vpwp_in, up2_in, vp2_in, up3_in, vp3_in, rtm_in, & + !$acc wprtp_in, thlm_in, wpthlp_in, rtp2_in, & + !$acc rtp3_in, thlp2_in, thlp3_in, rtpthlp_in, wp2_in, wp3_in, & + !$acc p_in_Pa, exner, rcm_inout, cloud_frac_inout, wpthvp_in, wp2thvp_in, & + !$acc rtpthvp_in, thlpthvp_in, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, um_pert_inout, & + !$acc vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & + !$acc copyout( rcm_in_layer_out, cloud_cover_out, wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & + !$acc cloudy_updraft_frac_out, cloudy_downdraft_frac_out, invrs_tau_zm_out, khzt_out, & + !$acc khzm_out, thlprcp_out, qclvar_out ) + + !$acc data if( sclr_dim > 0 ) & + !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & + !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & + !$acc copy( edsclr_in ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & + !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') + do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3651,6 +3746,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo ! end time loop call t_startf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:acc_copyout') + !$acc end data + !$acc end data + !$acc end data + !$acc end data + call t_stopf('clubb_tend_cam:acc_copyout') + if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then From 6a38ec26aa8548ed86a63e03a59aef02f1148126 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Sat, 12 Oct 2024 15:29:46 -0600 Subject: [PATCH 04/89] Replacing vector notation with loops, rearranging some things, general cleanup. --- src/physics/cam/clubb_intr.F90 | 763 ++++++++++++++++++--------------- 1 file changed, 420 insertions(+), 343 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 4b30e503ac..c1d2008ba2 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -1477,7 +1477,7 @@ subroutine clubb_ini_cam(pbuf2d) logical, parameter :: l_input_fields = .false. ! Always false for CAM-CLUBB. logical, parameter :: l_update_pressure = .false. ! Always false for CAM-CLUBB. - integer :: nlev, ierr=0 + integer :: ierr=0 real(r8) :: & C1, C1b, C1c, C2rt, C2thl, C2rtthl, & @@ -1505,8 +1505,6 @@ subroutine clubb_ini_cam(pbuf2d) !----- Begin Code ----- - nlev = pver + 1 - top_lev - if (core_rknd /= r8) then call endrun('clubb_ini_cam: CLUBB library core_rknd must match CAM r8 and it does not') end if @@ -1748,7 +1746,7 @@ subroutine clubb_ini_cam(pbuf2d) ! at each time step, which is why dummy arrays are read in here for heights ! as they are immediately overwrote. !$OMP PARALLEL - call check_clubb_settings_api( nlev+1, clubb_params_single_col, & ! Intent(in) + call check_clubb_settings_api( pverp+1-top_lev, clubb_params_single_col, & ! Intent(in) l_implemented, & ! Intent(in) l_input_fields, & ! Intent(in) clubb_config_flags, & ! intent(in) @@ -1887,7 +1885,7 @@ subroutine clubb_ini_cam(pbuf2d) if (stats_metadata%l_stats) then call stats_init_clubb( .true., dum1, dum2, & - nlev+1, nlev+1, nlev+1, dum3, & + pverp+1-top_lev, pverp+1-top_lev, pverp+1-top_lev, dum3, & stats_zt(:), stats_zm(:), stats_sfc(:), & stats_rad_zt(:), stats_rad_zm(:)) @@ -2346,10 +2344,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclrp3, & ! sclr'^3 (thermo. levels) [{units vary}^3] sclrprtp, & ! sclr'rt' (momentum levels) [{units vary} (kg/kg)] sclrpthlp, & ! sclr'thlp' (momentum levels) [{units vary} (K)] - wpsclrp ! w'sclr' (momentum levels) [{units vary} m/s] - - real(r8), dimension(state%ncol,pverp,sclr_dim) :: & - sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] + wpsclrp, & ! w'sclr' (momentum levels) [{units vary} m/s] + sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] real(r8), dimension(state%ncol,pverp+1-top_lev,edsclr_dim) :: & edsclrm_forcing, & ! Eddy passive scalar forcing [{units vary}/s] @@ -2576,8 +2572,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: temp2d(pcols,pver), temp2dp(pcols,pverp) ! temporary array for holding scaled outputs - integer :: nlev - intrinsic :: max character(len=*), parameter :: subr='clubb_tend_cam' @@ -2591,10 +2585,19 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8), dimension(state%ncol,nparams) :: & clubb_params ! Adjustable CLUBB parameters (C1, C2 ...) + + integer :: & + nzm_clubb, & + nzt_clubb, & + sclr, & + edsclr #endif - det_s(:) = 0.0_r8 - det_ice(:) = 0.0_r8 + + do i = 1, pcols + det_s(i) = 0.0_r8 + det_ice(i) = 0.0_r8 + end do #ifdef CLUBB_SGS @@ -2609,33 +2612,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! - - nlev = pver + 1 - top_lev - - call t_startf('clubb_tend_cam:NAR') - rtp2_zt_out = 0._r8 - thl2_zt_out = 0._r8 - wp2_zt_out = 0._r8 - pdfp_rtp2 = 0._r8 - wm_zt_out = 0._r8 - - temp2d = 0._r8 - temp2dp = 0._r8 - - dl_rad = clubb_detliq_rad - di_rad = clubb_detice_rad - dt_low = clubb_detphase_lowtemp - - frac_limit = 0.01_r8 - ic_limit = 1.e-12_r8 - inv_rh2o = 1._r8/rh2o - - if (clubb_do_adv) then - apply_const = 1._r8 ! Initialize to one, only if CLUBB's moments are advected - else - apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected - endif - ! Get indicees for cloud and ice mass and cloud and ice number call cnst_get_ind('Q',ixq) call cnst_get_ind('CLDLIQ',ixcldliq) @@ -2643,28 +2619,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call cnst_get_ind('NUMLIQ',ixnumliq) call cnst_get_ind('NUMICE',ixnumice) - if (clubb_do_icesuper) then - call pbuf_get_field(pbuf, naai_idx, naai) - end if - - ! Initialize physics tendency arrays, copy the state to state1 array to use in this routine - call physics_ptend_init(ptend_all, state%psetcols, 'clubb') - - ! Copy the state to state1 array to use in this routine - call physics_state_copy(state, state1) - - ! Constituents are all treated as dry mmr by clubb. Convert the water species to - ! a dry basis. - call set_wet_to_dry(state1, convert_cnst_type='wet') - - if (clubb_do_liqsupersat) then - call pbuf_get_field(pbuf, npccn_idx, npccn) - endif - - ! Determine number of columns and which chunk computation is to be performed on - ncol = state%ncol - lchnk = state%lchnk - ! Determine time step of physics buffer itim_old = pbuf_old_tim_idx() @@ -2761,17 +2715,110 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_get_field(pbuf, vpwp_clubb_gw_mc_idx, vpwp_clubb_gw_mc ) call pbuf_get_field(pbuf, wpthlp_clubb_gw_mc_idx, wpthlp_clubb_gw_mc ) + if (clubb_do_icesuper) then + call pbuf_get_field(pbuf, naai_idx, naai) + end if + + ! Initialize physics tendency arrays, copy the state to state1 array to use in this routine + call physics_ptend_init(ptend_all, state%psetcols, 'clubb') + + ! Copy the state to state1 array to use in this routine + call physics_state_copy(state, state1) + + ! Constituents are all treated as dry mmr by clubb. Convert the water species to + ! a dry basis. + call set_wet_to_dry(state1, convert_cnst_type='wet') + + if (clubb_do_liqsupersat) then + call pbuf_get_field(pbuf, npccn_idx, npccn) + endif + + + + ! Determine number of columns and which chunk computation is to be performed on + ncol = state%ncol + lchnk = state%lchnk + + nzt_clubb = pver + 1 - top_lev + nzm_clubb = pverp + 1 - top_lev + + ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then - call init_pdf_params_api( pverp+1-top_lev, ncol, pdf_params_chnk(lchnk) ) - call init_pdf_params_api( pverp+1-top_lev, ncol, pdf_params_zm_chnk(lchnk) ) + call init_pdf_params_api( nzm_clubb, ncol, pdf_params_chnk(lchnk) ) + call init_pdf_params_api( nzm_clubb, ncol, pdf_params_zm_chnk(lchnk) ) end if - if ( .not. allocated(pdf_implicit_coefs_terms_chnk(lchnk)%coef_wp4_implicit) ) then - call init_pdf_implicit_coefs_terms_api( pverp+1-top_lev, ncol, sclr_dim, & - pdf_implicit_coefs_terms_chnk(lchnk) ) - end if + if ( .not. allocated(pdf_implicit_coefs_terms_chnk(lchnk)%coef_wp4_implicit) ) then + call init_pdf_implicit_coefs_terms_api( nzm_clubb, ncol, sclr_dim, & + pdf_implicit_coefs_terms_chnk(lchnk) ) + end if + + + !--------------------- Scalar Setting -------------------- + + dl_rad = clubb_detliq_rad + di_rad = clubb_detice_rad + dt_low = clubb_detphase_lowtemp + + frac_limit = 0.01_r8 + ic_limit = 1.e-12_r8 + inv_rh2o = 1._r8/rh2o + + ! Determine CLUBB time step and make it sub-step friendly + ! For now we want CLUBB time step to be 5 min since that is + ! what has been scientifically validated. However, there are certain + ! instances when a 5 min time step will not be possible (based on + ! host model time step or on macro-micro sub-stepping + dtime = clubb_timestep + + ! Now check to see if dtime is greater than the host model + ! (or sub stepped) time step. If it is, then simply + ! set it equal to the host (or sub step) time step. + ! This section is mostly to deal with small host model + ! time steps (or small sub-steps) + if (dtime > hdtime) then + dtime = hdtime + endif + + ! Now check to see if CLUBB time step divides evenly into + ! the host model time step. If not, force it to divide evenly. + ! We also want it to be 5 minutes or less. This section is + ! mainly for host model time steps that are not evenly divisible + ! by 5 minutes + if (mod(hdtime,dtime) .ne. 0) then + dtime = hdtime/2._r8 + do while (dtime > clubb_timestep) + dtime = dtime/2._r8 + end do + endif + + ! If resulting host model time step and CLUBB time step do not divide evenly + ! into each other, have model throw a fit. + if (mod(hdtime,dtime) .ne. 0) then + call endrun(subr//': CLUBB time step and HOST time step NOT compatible') + endif + + ! determine number of timesteps CLUBB core should be advanced, + ! host time step divided by CLUBB time step + nadv = max(hdtime/dtime,1._r8) + + + ! Set stats output and increment equal to CLUBB and host dt + stats_metadata%stats_tsamp = dtime + stats_metadata%stats_tout = hdtime + + stats_nsamp = nint(stats_metadata%stats_tsamp/dtime) + stats_nout = nint(stats_metadata%stats_tout/dtime) + + + if (clubb_do_adv) then + apply_const = 1._r8 ! Initialize to one, only if CLUBB's moments are advected + else + apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected + endif + ! Initialize the apply_const variable (note special logic is due to eularian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then @@ -2779,15 +2826,188 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! from moments since it has not been added yet endif + + !--------------------- Initializations -------------------- + + ! Set the ztodt timestep in pbuf for SILHS ztodtptr(:) = 1.0_r8*hdtime + + ! Determine Coriolis force at given latitude. This is never used + ! when CLUBB is implemented in a host model, therefore just set + ! to zero. + fcor(:) = 0._r8 + + call t_startf('clubb_tend_cam:NAR') + + do i = 1, pcols + do k = 1, pverp + rtp2_zt_out(i,k) = 0._r8 + thl2_zt_out(i,k) = 0._r8 + wp2_zt_out(i,k) = 0._r8 + pdfp_rtp2(i,k) = 0._r8 + wm_zt_out(i,k) = 0._r8 + temp2dp(i,k) = 0._r8 + end do + end do + + + do i = 1, pcols + do k = 1, pver + temp2d(i,k) = 0._r8 + end do + end do + + ! Initialize forcings for transported scalars to zero + do sclr = 1, sclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + sclrm_forcing(i,k,sclr) = 0._r8 + sclrm(i,k,sclr) = 0._r8 + end do + end do + end do + + do edsclr = 1, edsclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + edsclrm_forcing(i,k,edsclr) = 0._r8 + edsclr_in(i,k,edsclr) = 0._r8 + end do + end do + end do + + + ! Initialize EDMF outputs + if (do_clubb_mf) then + do k = 1, pverp + do i = 1, pcols + mf_dry_a_output(i,k) = 0._r8 + mf_moist_a_output(i,k) = 0._r8 + mf_dry_w_output(i,k) = 0._r8 + mf_moist_w_output(i,k) = 0._r8 + mf_dry_qt_output(i,k) = 0._r8 + mf_moist_qt_output(i,k) = 0._r8 + mf_dry_thl_output(i,k) = 0._r8 + mf_moist_thl_output(i,k) = 0._r8 + mf_dry_u_output(i,k) = 0._r8 + mf_moist_u_output(i,k) = 0._r8 + mf_dry_v_output(i,k) = 0._r8 + mf_moist_v_output(i,k) = 0._r8 + mf_moist_qc_output(i,k) = 0._r8 + s_ae_output(i,k) = 0._r8 + s_aw_output(i,k) = 0._r8 + s_awthl_output(i,k) = 0._r8 + s_awqt_output(i,k) = 0._r8 + s_awql_output(i,k) = 0._r8 + s_awqi_output(i,k) = 0._r8 + s_awu_output(i,k) = 0._r8 + s_awv_output(i,k) = 0._r8 + mf_thlflx_output(i,k) = 0._r8 + mf_qtflx_output(i,k) = 0._r8 + end do + end do + end if + + ! Define surface sources for transported variables for diffusion, will + ! be zero as these tendencies are done in vertical_diffusion + do edsclr = 1, edsclr_dim + do i = 1, ncol + wpedsclrp_sfc(i,edsclr) = 0._r8 + end do + end do + + + ! Define forcings from CAM to CLUBB as zero for momentum and thermo, + ! forcings already applied through CAM + do k = 1, nzm_clubb + do i = 1, ncol + thlm_forcing(i,k) = 0._r8 + rtm_forcing(i,k) = 0._r8 + um_forcing(i,k) = 0._r8 + vm_forcing(i,k) = 0._r8 + + + rtm_ref(i,k) = 0.0_r8 + thlm_ref(i,k) = 0.0_r8 + um_ref(i,k) = 0.0_r8 + vm_ref(i,k) = 0.0_r8 + ug(i,k) = 0.0_r8 + vg(i,k) = 0.0_r8 + + ! Perturbed winds are not used in CAM + um_pert_inout(i,k) = 0.0_r8 + vm_pert_inout(i,k) = 0.0_r8 + upwp_pert_inout(i,k) = 0.0_r8 + vpwp_pert_inout(i,k) = 0.0_r8 + end do + end do + + do i = 1, ncol + ! Perturbed winds are not used in CAM + upwp_sfc_pert(i) = 0.0_r8 + vpwp_sfc_pert(i) = 0.0_r8 + + ! higher order scalar stuff, put to zero + wpsclrp_sfc(i,sclr) = 0._r8 + end do + + ! Initialize these to prevent crashing behavior + do k=1,nzm_clubb + do i=1,ncol + wprcp_out(i,k) = 0._r8 + rcm_in_layer_out(i,k) = 0._r8 + cloud_cover_out(i,k) = 0._r8 + khzm_out(i,k) = 0._r8 + khzt_out(i,k) = 0._r8 + end do + end do + + ! higher order scalar stuff, put to zero + do sclr = 1, sclr_dim + do k = 1, nzm_clubb + do i=1, ncol + sclrm(i,k,sclr) = 0._r8 + wpsclrp(i,k,sclr) = 0._r8 + sclrp2(i,k,sclr) = 0._r8 + sclrp3(i,k,sclr) = 0._r8 + sclrprtp(i,k,sclr) = 0._r8 + sclrpthlp(i,k,sclr) = 0._r8 + sclrpthvp_inout(i,k,sclr) = 0._r8 + end do + end do + end do + + do ixind=1, hydromet_dim + do k=1, nzm_clubb + do i=1, ncol + hydromet(i,k,ixind) = 0._r8 + wphydrometp(i,k,ixind) = 0._r8 + wp2hmp(i,k,ixind) = 0._r8 + rtphmp_zt(i,k,ixind) = 0._r8 + thlphmp_zt(i,k,ixind) = 0._r8 + end do + end do + end do + + ! need to initialize macmic coupling to zero + if (macmic_it==1) then + ttend_clubb_mc(:ncol,:) = 0._r8 + upwp_clubb_gw_mc(:ncol,:) = 0._r8 + vpwp_clubb_gw_mc(:ncol,:) = 0._r8 + thlp2_clubb_gw_mc(:ncol,:) = 0._r8 + wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + end if + + + ! Define the grid box size. CLUBB needs this information to determine what ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids call grid_size(state1, grid_dx, grid_dy) - + call t_stopf('clubb_tend_cam:NAR') if (clubb_do_icesuper) then @@ -2805,10 +3025,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call physics_ptend_init(ptend_loc, state%psetcols, 'iceadj', ls=.true., lq=lq2 ) - stend(:ncol,:)=0._r8 - qvtend(:ncol,:)=0._r8 - qitend(:ncol,:)=0._r8 - initend(:ncol,:)=0._r8 + do i = 1, ncol + do k = 1, pver + stend(i,k) = 0._r8 + qvtend(i,k) = 0._r8 + qitend(i,k) = 0._r8 + initend(i,k) = 0._r8 + end do + end do call t_startf('clubb_tend_cam:ice_macro_tend') call ice_macro_tend(naai(1:ncol,top_lev:pver), state1%t(1:ncol,top_lev:pver), & @@ -2819,10 +3043,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:ice_macro_tend') ! update local copy of state with the tendencies - ptend_loc%q(:ncol,top_lev:pver,1)=qvtend(:ncol,top_lev:pver) - ptend_loc%q(:ncol,top_lev:pver,ixcldice)=qitend(:ncol,top_lev:pver) - ptend_loc%q(:ncol,top_lev:pver,ixnumice)=initend(:ncol,top_lev:pver) - ptend_loc%s(:ncol,top_lev:pver)=stend(:ncol,top_lev:pver) + do i = 1, ncol + do k = top_lev, pver + ptend_loc%q(i,k,1) = qvtend(i,k) + ptend_loc%q(i,k,ixcldice) = qitend(i,k) + ptend_loc%q(i,k,ixnumice) = initend(i,k) + ptend_loc%s(i,k) = stend(i,k) + end do + end do ! Add the ice tendency to the output tendency call physics_ptend_sum(ptend_loc, ptend_all, ncol) @@ -2830,8 +3058,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! ptend_loc is reset to zero by this call call physics_update(state1, ptend_loc, hdtime) - !Write output for tendencies: - temp2d(:ncol,:pver) = stend(:ncol,:pver)/cpairv(:ncol,:pver,lchnk) + ! Write output for tendencies: + do i = 1, ncol + do k = 1, pver + temp2d(i,k) = stend(i,k) / cpairv(i,k,lchnk) + end do + end do + call outfld( 'TTENDICE', temp2d, pcols, lchnk ) call outfld( 'QVTENDICE', qvtend, pcols, lchnk ) call outfld( 'QITENDICE', qitend, pcols, lchnk ) @@ -2841,49 +3074,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') - ! Determine CLUBB time step and make it sub-step friendly - ! For now we want CLUBB time step to be 5 min since that is - ! what has been scientifically validated. However, there are certain - ! instances when a 5 min time step will not be possible (based on - ! host model time step or on macro-micro sub-stepping - dtime = clubb_timestep - - ! Now check to see if dtime is greater than the host model - ! (or sub stepped) time step. If it is, then simply - ! set it equal to the host (or sub step) time step. - ! This section is mostly to deal with small host model - ! time steps (or small sub-steps) - if (dtime > hdtime) then - dtime = hdtime - endif - - ! Now check to see if CLUBB time step divides evenly into - ! the host model time step. If not, force it to divide evenly. - ! We also want it to be 5 minutes or less. This section is - ! mainly for host model time steps that are not evenly divisible - ! by 5 minutes - if (mod(hdtime,dtime) .ne. 0) then - dtime = hdtime/2._r8 - do while (dtime > clubb_timestep) - dtime = dtime/2._r8 - end do - endif - - ! If resulting host model time step and CLUBB time step do not divide evenly - ! into each other, have model throw a fit. - if (mod(hdtime,dtime) .ne. 0) then - call endrun(subr//': CLUBB time step and HOST time step NOT compatible') - endif - - ! determine number of timesteps CLUBB core should be advanced, - ! host time step divided by CLUBB time step - nadv = max(hdtime/dtime,1._r8) - - ! Initialize forcings for transported scalars to zero - sclrm_forcing(:,:,:) = 0._r8 - edsclrm_forcing(:,:,:) = 0._r8 - sclrm(:,:,:) = 0._r8 - ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables @@ -2902,8 +3092,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! At each CLUBB call, initialize mean momentum and thermo CLUBB state ! from the CAM state - do k=1,pver ! loop over levels - do i=1,ncol ! loop over columns + do k = 1, pver + do i = 1, ncol rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) rvm(i,k) = state1%q(i,k,ixq) @@ -2913,12 +3103,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & * inv_exner_clubb(i,k) - if (clubb_do_adv) then - if (macmic_it == 1) then + enddo + enddo + + if (clubb_do_adv) then - ! Note that some of the moments below can be positive or negative. - ! Remove a constant that was added to prevent dynamics from clipping - ! them to prevent dynamics from making them positive. + if (macmic_it == 1) then + + ! Note that some of the moments below can be positive or negative. + ! Remove a constant that was added to prevent dynamics from clipping + ! them to prevent dynamics from making them positive. + do k = 1, pver + do i = 1, ncol thlp2(i,k) = state1%q(i,k,ixthlp2) rtp2(i,k) = state1%q(i,k,ixrtp2) rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - (rtpthlp_const*apply_const) @@ -2928,13 +3124,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wp3(i,k) = state1%q(i,k,ixwp3) - (wp3_const*apply_const) up2(i,k) = state1%q(i,k,ixup2) vp2(i,k) = state1%q(i,k,ixvp2) - endif - endif + enddo + enddo - enddo - enddo + endif - if (clubb_do_adv) then ! If not last step of macmic loop then set apply_const back to ! zero to prevent output from being corrupted. if (macmic_it == cld_macmic_num_steps) then @@ -2942,98 +3136,71 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & else apply_const = 0._r8 endif - endif - rtm(1:ncol,pverp) = rtm(1:ncol,pver) - um(1:ncol,pverp) = state1%u(1:ncol,pver) - vm(1:ncol,pverp) = state1%v(1:ncol,pver) - thlm(1:ncol,pverp) = thlm(1:ncol,pver) + do i = 1, ncol + thlp2(i,pverp) = thlp2(i,pver) + rtp2(i,pverp) = rtp2(i,pver) + rtpthlp(i,pverp) = rtpthlp(i,pver) + wpthlp(i,pverp) = wpthlp(i,pver) + wprtp(i,pverp) = wprtp(i,pver) + wp2(i,pverp) = wp2(i,pver) + wp3(i,pverp) = wp3(i,pver) + up2(i,pverp) = up2(i,pver) + vp2(i,pverp) = vp2(i,pver) + end do - if (clubb_do_adv) then - thlp2(1:ncol,pverp) = thlp2(1:ncol,pver) - rtp2(1:ncol,pverp) = rtp2(1:ncol,pver) - rtpthlp(1:ncol,pverp) = rtpthlp(1:ncol,pver) - wpthlp(1:ncol,pverp) = wpthlp(1:ncol,pver) - wprtp(1:ncol,pverp) = wprtp(1:ncol,pver) - wp2(1:ncol,pverp) = wp2(1:ncol,pver) - wp3(1:ncol,pverp) = wp3(1:ncol,pver) - up2(1:ncol,pverp) = up2(1:ncol,pver) - vp2(1:ncol,pverp) = vp2(1:ncol,pver) endif + + do i = 1, ncol + rtm(i,pverp) = rtm(i,pver) + um(i,pverp) = state1%u(i,pver) + vm(i,pverp) = state1%v(i,pver) + thlm(i,pverp) = thlm(i,pver) + end do + ! Compute virtual potential temperature, which is needed for CLUBB - do k=1,pver - do i=1,ncol + do k = 1, pver + do i = 1, ncol thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& -state1%q(i,k,ixcldliq)) enddo enddo - call physics_ptend_init(ptend_loc,state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq) + call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists troplev(:) = 0 !REMOVECAM_END - call tropopause_findChemTrop(state, troplev) - - ! Initialize EDMF outputs - if (do_clubb_mf) then - mf_dry_a_output(:,:) = 0._r8 - mf_moist_a_output(:,:) = 0._r8 - mf_dry_w_output(:,:) = 0._r8 - mf_moist_w_output(:,:) = 0._r8 - mf_dry_qt_output(:,:) = 0._r8 - mf_moist_qt_output(:,:) = 0._r8 - mf_dry_thl_output(:,:) = 0._r8 - mf_moist_thl_output(:,:) = 0._r8 - mf_dry_u_output(:,:) = 0._r8 - mf_moist_u_output(:,:) = 0._r8 - mf_dry_v_output(:,:) = 0._r8 - mf_moist_v_output(:,:) = 0._r8 - mf_moist_qc_output(:,:) = 0._r8 - s_ae_output(:,:) = 0._r8 - s_aw_output(:,:) = 0._r8 - s_awthl_output(:,:) = 0._r8 - s_awqt_output(:,:) = 0._r8 - s_awql_output(:,:) = 0._r8 - s_awqi_output(:,:) = 0._r8 - s_awu_output(:,:) = 0._r8 - s_awv_output(:,:) = 0._r8 - mf_thlflx_output(:,:) = 0._r8 - mf_qtflx_output(:,:) = 0._r8 - end if + call tropopause_findChemTrop( state, troplev ) - ! Determine Coriolis force at given latitude. This is never used - ! when CLUBB is implemented in a host model, therefore just set - ! to zero. - fcor(:) = 0._r8 ! Define the CLUBB momentum grid (in height, units of m) - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol zi_g(i,k) = state1%zi(i,pverp-k+1)-state1%zi(i,pver+1) end do end do ! Define the CLUBB thermodynamic grid (in units of m) - do k=1, nlev + do k=1, nzt_clubb do i=1, ncol zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) end do end do + ! Thermodynamic ghost point is below surface + do i=1, ncol + zt_g(i,1) = -1._r8*zt_g(i,2) + end do + do k=1, pver do i=1, ncol dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness end do end do - ! Thermodynamic ghost point is below surface - do i=1, ncol - zt_g(i,1) = -1._r8*zt_g(i,2) - end do - do i=1, ncol ! Set the elevation of the surface sfc_elevation(i) = state1%zi(i,pver+1) @@ -3041,8 +3208,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core - do k=1,nlev - do i=1, ncol + do k = 1, nzt_clubb + do i = 1, ncol ! base state (dry) variables rho_ds_zt(i,k+1) = rga*(state1%pdeldry(i,pver-k+1)/dz_g(i,pver-k+1)) invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) @@ -3060,19 +3227,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rfrzm(i,k+1) = state1%q(i,pver-k+1,ixcldice) radf(i,k+1) = radf_clubb(i,pver-k+1) qrl_clubb(i,k+1) = qrl(i,pver-k+1)/(cpairv(i,k,lchnk)*state1%pdeldry(i,pver-k+1)) - end do - end do - ! Compute mean w wind on thermo grid, convert from omega to w - do k=1,nlev - do i=1,ncol + ! Compute mean w wind on thermo grid, convert from omega to w wm_zt(i,k+1) = -1._r8*(state1%omega(i,pver-k+1)-state1%omega(i,pver))/(rho_zt(i,k+1)*gravit) end do end do ! Below computes the same stuff for the ghost point. May or may ! not be needed, just to be safe to avoid NaN's - do i=1, ncol + do i = 1, ncol thv_ds_zt(i,1) = thv_ds_zt(i,2) rho_ds_zt(i,1) = rho_ds_zt(i,2) invrs_rho_ds_zt(i,1) = invrs_rho_ds_zt(i,2) @@ -3137,20 +3300,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if - ! Define surface sources for transported variables for diffusion, will - ! be zero as these tendencies are done in vertical_diffusion - do ixind=1,edsclr_dim - do i=1,ncol - wpedsclrp_sfc(i,ixind) = 0._r8 - end do - end do - - ! Set stats output and increment equal to CLUBB and host dt - stats_metadata%stats_tsamp = dtime - stats_metadata%stats_tout = hdtime - - stats_nsamp = nint(stats_metadata%stats_tsamp/dtime) - stats_nout = nint(stats_metadata%stats_tout/dtime) ! Heights need to be set at each timestep. Therefore, recall ! setup_grid and setup_parameters for this. @@ -3159,8 +3308,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Important note: do not make any calls that use CLUBB grid-height ! operators (such as zt2zm_api, etc.) until AFTER the ! call to setup_grid_heights_api. - call setup_grid_api( nlev+1, ncol, sfc_elevation, l_implemented, & ! intent(in) - grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nlev+1), & ! intent(in) + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) + grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) gr ) ! intent(out) @@ -3171,32 +3320,17 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call setup_parameters_api( zi_g(:,2), clubb_params, gr, ncol, grid_type, & ! intent(in) clubb_config_flags%l_prescribed_avg_deltaz, & ! intent(in) lmin, nu_vert_res_dep, err_code ) ! intent(out) + if ( err_code == clubb_fatal_error ) then call endrun(subr//': Fatal error in CLUBB setup_parameters') end if - - ! Define forcings from CAM to CLUBB as zero for momentum and thermo, - ! forcings already applied through CAM - thlm_forcing(:,:) = 0._r8 - rtm_forcing(:,:) = 0._r8 - um_forcing(:,:) = 0._r8 - vm_forcing(:,:) = 0._r8 - - - rtm_ref(:,:) = 0.0_r8 - thlm_ref(:,:) = 0.0_r8 - um_ref(:,:) = 0.0_r8 - vm_ref(:,:) = 0.0_r8 - ug(:,:) = 0.0_r8 - vg(:,:) = 0.0_r8 - ! Add forcings for SILHS covariance contributions - rtp2_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, rtp2_mc_zt(1:ncol,:) ) - thlp2_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, thlp2_mc_zt(1:ncol,:) ) - wprtp_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, wprtp_mc_zt(1:ncol,:) ) - wpthlp_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, wpthlp_mc_zt(1:ncol,:) ) - rtpthlp_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) + rtp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtp2_mc_zt(1:ncol,:) ) + thlp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, thlp2_mc_zt(1:ncol,:) ) + wprtp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wprtp_mc_zt(1:ncol,:) ) + wpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wpthlp_mc_zt(1:ncol,:) ) + rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) ! Zero out SILHS covariance contribution terms rtp2_mc_zt(:,:) = 0.0_r8 @@ -3208,11 +3342,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute some inputs from the thermodynamic grid ! to the momentum grid - rho_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, rho_ds_zt ) - rho_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, rho_zt ) - invrs_rho_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, invrs_rho_ds_zt ) - thv_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, thv_ds_zt ) - wm_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, wm_zt ) + rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_ds_zt ) + rho_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_zt ) + invrs_rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, invrs_rho_ds_zt ) + thv_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, thv_ds_zt ) + wm_zm = zt2zm_api( nzm_clubb, ncol, gr, wm_zt ) ! Surface fluxes provided by host model do i=1,ncol @@ -3241,16 +3375,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vpwp_sfc(i) = cam_in%wsy(i)/rho_ds_zm(i,1) ! Surface zonal momentum flux end do endif - - ! Perturbed winds are not used in CAM - upwp_sfc_pert = 0.0_r8 - vpwp_sfc_pert = 0.0_r8 call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') + ! Need to flip arrays around for CLUBB core - do k=1,nlev+1 - do i=1,ncol + do k = 1, nzm_clubb + do i = 1, ncol + um_in(i,k) = um(i,pverp-k+1) vm_in(i,k) = vm(i,pverp-k+1) upwp_in(i,k) = upwp(i,pverp-k+1) @@ -3291,7 +3423,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & pdf_params_zm_chnk(lchnk)%mixt_frac(i,k) = pdf_zm_mixt_frac(i,pverp-k+1) end if - sclrpthvp_inout(i,k,:) = 0._r8 wp2rtp_inout(i,k) = wp2rtp(i,pverp-k+1) wp2thlp_inout(i,k) = wp2thlp(i,pverp-k+1) uprcp_inout(i,k) = uprcp(i,pverp-k+1) @@ -3306,63 +3437,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Perturbed winds are not used in CAM - um_pert_inout = 0.0_r8 - vm_pert_inout = 0.0_r8 - upwp_pert_inout = 0.0_r8 - vpwp_pert_inout = 0.0_r8 - - do k=2,nlev+1 + do k=2, nzm_clubb do i=1,ncol pre_in(i,k) = prer_evap(i,pverp-k+1) end do end do do i=1,ncol - pre_in(i,1) = pre_in(i,2) - end do - - do i=1,ncol - rcm_inout(i,1) = rcm_inout(i,2) - end do - - ! Initialize these to prevent crashing behavior - do k=1,nlev+1 - do i=1,ncol - wprcp_out(i,k) = 0._r8 - rcm_in_layer_out(i,k) = 0._r8 - cloud_cover_out(i,k) = 0._r8 - edsclr_in(i,k,:) = 0._r8 - khzm_out(i,k) = 0._r8 - khzt_out(i,k) = 0._r8 - end do - end do - - ! higher order scalar stuff, put to zero - do ixind=1, sclr_dim - do k=1, nlev+1 - do i=1, ncol - sclrm(i,k,ixind) = 0._r8 - wpsclrp(i,k,ixind) = 0._r8 - sclrp2(i,k,ixind) = 0._r8 - sclrp3(i,k,ixind) = 0._r8 - sclrprtp(i,k,ixind) = 0._r8 - sclrpthlp(i,k,ixind) = 0._r8 - wpsclrp_sfc(i,ixind) = 0._r8 - end do - end do - end do - - do ixind=1, hydromet_dim - do k=1, nlev+1 - do i=1, ncol - hydromet(i,k,ixind) = 0._r8 - wphydrometp(i,k,ixind) = 0._r8 - wp2hmp(i,k,ixind) = 0._r8 - rtphmp_zt(i,k,ixind) = 0._r8 - thlphmp_zt(i,k,ixind) = 0._r8 - end do - end do + pre_in(i,1) = pre_in(i,2) + rcm_inout(i,1) = rcm_inout(i,2) end do ! pressure,exner on momentum grid needed for mass flux calc. @@ -3382,7 +3465,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_exner_zt(i,1) = invrs_exner_zt(i,2) end do - kappa_zm(1:ncol,:) = zt2zm_api(pverp+1-top_lev, ncol, gr, kappa_zt(1:ncol,:)) + kappa_zm(1:ncol,:) = zt2zm_api(nzm_clubb, ncol, gr, kappa_zt(1:ncol,:)) do k=1,pverp do i=1,ncol @@ -3397,17 +3480,17 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_adv) then if (macmic_it == 1) then - wp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wp2_in ) - wpthlp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wpthlp_in ) - wprtp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wprtp_in ) - up2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, up2_in ) - vp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, vp2_in ) - thlp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, thlp2_in ) - rtp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, rtp2_in ) - rtpthlp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, rtpthlp_in ) + wp2_in = zt2zm_api(nzm_clubb, ncol, gr, wp2_in ) + wpthlp_in = zt2zm_api(nzm_clubb, ncol, gr, wpthlp_in ) + wprtp_in = zt2zm_api(nzm_clubb, ncol, gr, wprtp_in ) + up2_in = zt2zm_api(nzm_clubb, ncol, gr, up2_in ) + vp2_in = zt2zm_api(nzm_clubb, ncol, gr, vp2_in ) + thlp2_in = zt2zm_api(nzm_clubb, ncol, gr, thlp2_in ) + rtp2_in = zt2zm_api(nzm_clubb, ncol, gr, rtp2_in ) + rtpthlp_in = zt2zm_api(nzm_clubb, ncol, gr, rtpthlp_in ) - do k=1,nlev+1 - do i=1,ncol + do k = 1, nzm_clubb + do i = 1, ncol thlp2_in(i,k) = max(thl_tol**2,thlp2_in(i,k)) rtp2_in(i,k) = max(rt_tol**2,rtp2_in(i,k)) wp2_in(i,k) = max(w_tol_sqd,wp2_in(i,k)) @@ -3426,7 +3509,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & icnt = icnt+1 - do k=1,nlev + do k=1,nzt_clubb do i=1,ncol edsclr_in(i,k+1,icnt) = state1%q(i,pver-k+1,ixind) end do @@ -3441,7 +3524,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_l_do_expldiff_rtm_thlm) then - do k=1,nlev + do k=1,nzt_clubb do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) edsclr_in(i,k+1,icnt+2) = rtm(i,pver-k+1) @@ -3455,12 +3538,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - ! need to initialize macmic coupling to zero - if (macmic_it==1) ttend_clubb_mc(:ncol,:) = 0._r8 - if (macmic_it==1) upwp_clubb_gw_mc(:ncol,:) = 0._r8 - if (macmic_it==1) vpwp_clubb_gw_mc(:ncol,:) = 0._r8 - if (macmic_it==1) thlp2_clubb_gw_mc(:ncol,:) = 0._r8 - if (macmic_it==1) wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 call t_stopf('clubb_tend_cam:flip-index') @@ -3576,8 +3653,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_dzt(i,:) = 1._r8/dzt(i,:) end do - rtm_zm_in(1:ncol,:) = zt2zm_api( pverp+1-top_lev, ncol, gr, rtm_in(1:ncol,:) ) - thlm_zm_in(1:ncol,:) = zt2zm_api( pverp+1-top_lev, ncol, gr, thlm_in(1:ncol,:) ) + rtm_zm_in(1:ncol,:) = zt2zm_api( nzm_clubb, ncol, gr, rtm_in(1:ncol,:) ) + thlm_zm_in(1:ncol,:) = zt2zm_api( nzm_clubb, ncol, gr, thlm_in(1:ncol,:) ) do i=1, ncol call integrate_mf( pverp, dzt(i,:), zi_g(i,:), p_in_Pa_zm(i,:), invrs_exner_zm(i,:), & ! input @@ -3620,7 +3697,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Advance CLUBB CORE one timestep in the future call t_startf('clubb_tend_cam:advance_clubb_core_api') - call advance_clubb_core_api( gr, pverp+1-top_lev, ncol, & + call advance_clubb_core_api( gr, nzm_clubb, ncol, & l_implemented, dtime, fcor, sfc_elevation, & hydromet_dim, & sclr_dim, sclr_tol, edsclr_dim, sclr_idx, & @@ -3682,14 +3759,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (do_rainturb) then - do k=1,nlev+1 + do k=1,nzm_clubb do i=1,ncol rvm_in(i,k) = rtm_in(i,k) - rcm_inout(i,k) end do end do call t_startf('clubb_tend_cam:update_xp2_mc_api') - call update_xp2_mc_api( gr, nlev+1, ncol, dtime, cloud_frac_inout, & + call update_xp2_mc_api( gr, nzm_clubb, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & rtp2_mc_out, thlp2_mc_out, & @@ -3697,7 +3774,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rtpthlp_mc_out) call t_stopf('clubb_tend_cam:update_xp2_mc_api') - do k=1,nlev+1 + do k=1,nzm_clubb do i=1,ncol dum1 = (1._r8 - cam_in%landfrac(i)) @@ -3715,12 +3792,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (do_cldcool) then call t_startf('clubb_tend_cam:do_cldcool') - rcm_out_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, rcm_inout ) - qrl_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, qrl_clubb ) + rcm_out_zm = zt2zm_api(nzm_clubb, ncol, gr, rcm_inout ) + qrl_zm = zt2zm_api(nzm_clubb, ncol, gr, qrl_clubb ) thlp2_rad_out(:,:) = 0._r8 do i=1, ncol - call calculate_thlp2_rad_api(nlev+1, rcm_out_zm(i,:), thlprcp_out(i,:), qrl_zm(i,:), clubb_params(i,:), & + call calculate_thlp2_rad_api(nzm_clubb, rcm_out_zm(i,:), thlprcp_out(i,:), qrl_zm(i,:), clubb_params(i,:), & thlp2_rad_out(i,:)) end do @@ -3756,16 +3833,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then - wp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) - wpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wpthlp_in ) - wprtp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wprtp_in ) - up2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, up2_in ) - vp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, vp2_in ) - thlp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) - rtp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) - rtpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtpthlp_in ) + wp2_in = zm2zt_api( nzm_clubb, ncol, gr, wp2_in ) + wpthlp_in = zm2zt_api( nzm_clubb, ncol, gr, wpthlp_in ) + wprtp_in = zm2zt_api( nzm_clubb, ncol, gr, wprtp_in ) + up2_in = zm2zt_api( nzm_clubb, ncol, gr, up2_in ) + vp2_in = zm2zt_api( nzm_clubb, ncol, gr, vp2_in ) + thlp2_in = zm2zt_api( nzm_clubb, ncol, gr, thlp2_in ) + rtp2_in = zm2zt_api( nzm_clubb, ncol, gr, rtp2_in ) + rtpthlp_in = zm2zt_api( nzm_clubb, ncol, gr, rtpthlp_in ) - do k=1,nlev+1 + do k=1,nzm_clubb do i=1, ncol thlp2_in(i,k) = max(thl_tol**2, thlp2_in(i,k)) rtp2_in(i,k) = max(rt_tol**2, rtp2_in(i,k)) @@ -3781,14 +3858,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Convert RTP2 and THLP2 to thermo grid for output call t_startf('clubb_tend_cam:NAR') - rtp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) - thl2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) - wp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) + rtp2_zt = zm2zt_api( nzm_clubb, ncol, gr, rtp2_in ) + thl2_zt = zm2zt_api( nzm_clubb, ncol, gr, thlp2_in ) + wp2_zt = zm2zt_api( nzm_clubb, ncol, gr, wp2_in ) call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') ! Arrays need to be "flipped" to CAM grid - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol um(i,pverp-k+1) = um_in(i,k) vm(i,pverp-k+1) = vm_in(i,k) @@ -3863,7 +3940,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpthlp_clubb_gw(:ncol,:) = wpthlp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) end if - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & @@ -3881,7 +3958,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do do ixind=1,edsclr_dim - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) end do @@ -3889,7 +3966,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do if (do_clubb_mf) then - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol mf_dry_a_output(i,pverp-k+1) = mf_dry_a(i,k) mf_moist_a_output(i,pverp-k+1) = mf_moist_a(i,k) From 94ba629400decfc87493c241db8d223916b9eee5 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Sun, 13 Oct 2024 22:43:21 -0600 Subject: [PATCH 05/89] More small changes --- src/physics/cam/clubb_intr.F90 | 451 +++++++++++++++++---------------- 1 file changed, 229 insertions(+), 222 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index c1d2008ba2..42e41c6e35 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2841,8 +2841,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') - do i = 1, pcols - do k = 1, pverp + do k = 1, pverp + do i = 1, pcols rtp2_zt_out(i,k) = 0._r8 thl2_zt_out(i,k) = 0._r8 wp2_zt_out(i,k) = 0._r8 @@ -2853,82 +2853,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do - do i = 1, pcols - do k = 1, pver - temp2d(i,k) = 0._r8 - end do - end do - - ! Initialize forcings for transported scalars to zero - do sclr = 1, sclr_dim - do i = 1, pcols - do k = 1, nzm_clubb - sclrm_forcing(i,k,sclr) = 0._r8 - sclrm(i,k,sclr) = 0._r8 - end do - end do - end do - - do edsclr = 1, edsclr_dim + do k = 1, pver do i = 1, pcols - do k = 1, nzm_clubb - edsclrm_forcing(i,k,edsclr) = 0._r8 - edsclr_in(i,k,edsclr) = 0._r8 - end do - end do - end do - - - ! Initialize EDMF outputs - if (do_clubb_mf) then - do k = 1, pverp - do i = 1, pcols - mf_dry_a_output(i,k) = 0._r8 - mf_moist_a_output(i,k) = 0._r8 - mf_dry_w_output(i,k) = 0._r8 - mf_moist_w_output(i,k) = 0._r8 - mf_dry_qt_output(i,k) = 0._r8 - mf_moist_qt_output(i,k) = 0._r8 - mf_dry_thl_output(i,k) = 0._r8 - mf_moist_thl_output(i,k) = 0._r8 - mf_dry_u_output(i,k) = 0._r8 - mf_moist_u_output(i,k) = 0._r8 - mf_dry_v_output(i,k) = 0._r8 - mf_moist_v_output(i,k) = 0._r8 - mf_moist_qc_output(i,k) = 0._r8 - s_ae_output(i,k) = 0._r8 - s_aw_output(i,k) = 0._r8 - s_awthl_output(i,k) = 0._r8 - s_awqt_output(i,k) = 0._r8 - s_awql_output(i,k) = 0._r8 - s_awqi_output(i,k) = 0._r8 - s_awu_output(i,k) = 0._r8 - s_awv_output(i,k) = 0._r8 - mf_thlflx_output(i,k) = 0._r8 - mf_qtflx_output(i,k) = 0._r8 - end do - end do - end if - - ! Define surface sources for transported variables for diffusion, will - ! be zero as these tendencies are done in vertical_diffusion - do edsclr = 1, edsclr_dim - do i = 1, ncol - wpedsclrp_sfc(i,edsclr) = 0._r8 + temp2d(i,k) = 0._r8 end do end do - ! Define forcings from CAM to CLUBB as zero for momentum and thermo, - ! forcings already applied through CAM do k = 1, nzm_clubb do i = 1, ncol + + ! Define forcings from CAM to CLUBB as zero for momentum and thermo, + ! forcings already applied through CAM thlm_forcing(i,k) = 0._r8 rtm_forcing(i,k) = 0._r8 um_forcing(i,k) = 0._r8 vm_forcing(i,k) = 0._r8 - rtm_ref(i,k) = 0.0_r8 thlm_ref(i,k) = 0.0_r8 um_ref(i,k) = 0.0_r8 @@ -2941,6 +2882,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_pert_inout(i,k) = 0.0_r8 upwp_pert_inout(i,k) = 0.0_r8 vpwp_pert_inout(i,k) = 0.0_r8 + + + ! Initialize these to prevent crashing behavior + wprcp_out(i,k) = 0._r8 + rcm_in_layer_out(i,k) = 0._r8 + cloud_cover_out(i,k) = 0._r8 + khzm_out(i,k) = 0._r8 + khzt_out(i,k) = 0._r8 end do end do @@ -2953,17 +2902,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpsclrp_sfc(i,sclr) = 0._r8 end do - ! Initialize these to prevent crashing behavior - do k=1,nzm_clubb - do i=1,ncol - wprcp_out(i,k) = 0._r8 - rcm_in_layer_out(i,k) = 0._r8 - cloud_cover_out(i,k) = 0._r8 - khzm_out(i,k) = 0._r8 - khzt_out(i,k) = 0._r8 - end do - end do - ! higher order scalar stuff, put to zero do sclr = 1, sclr_dim do k = 1, nzm_clubb @@ -2991,6 +2929,33 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! Initialize forcings for transported scalars to zero + do sclr = 1, sclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + sclrm_forcing(i,k,sclr) = 0._r8 + sclrm(i,k,sclr) = 0._r8 + end do + end do + end do + + do edsclr = 1, edsclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + edsclrm_forcing(i,k,edsclr) = 0._r8 + edsclr_in(i,k,edsclr) = 0._r8 + end do + end do + end do + + ! Define surface sources for transported variables for diffusion, will + ! be zero as these tendencies are done in vertical_diffusion + do edsclr = 1, edsclr_dim + do i = 1, ncol + wpedsclrp_sfc(i,edsclr) = 0._r8 + end do + end do + ! need to initialize macmic coupling to zero if (macmic_it==1) then ttend_clubb_mc(:ncol,:) = 0._r8 @@ -2999,9 +2964,40 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & thlp2_clubb_gw_mc(:ncol,:) = 0._r8 wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 end if - + ! Initialize EDMF outputs + if (do_clubb_mf) then + do k = 1, pverp + do i = 1, pcols + mf_dry_a_output(i,k) = 0._r8 + mf_moist_a_output(i,k) = 0._r8 + mf_dry_w_output(i,k) = 0._r8 + mf_moist_w_output(i,k) = 0._r8 + mf_dry_qt_output(i,k) = 0._r8 + mf_moist_qt_output(i,k) = 0._r8 + mf_dry_thl_output(i,k) = 0._r8 + mf_moist_thl_output(i,k) = 0._r8 + mf_dry_u_output(i,k) = 0._r8 + mf_moist_u_output(i,k) = 0._r8 + mf_dry_v_output(i,k) = 0._r8 + mf_moist_v_output(i,k) = 0._r8 + mf_moist_qc_output(i,k) = 0._r8 + s_ae_output(i,k) = 0._r8 + s_aw_output(i,k) = 0._r8 + s_awthl_output(i,k) = 0._r8 + s_awqt_output(i,k) = 0._r8 + s_awql_output(i,k) = 0._r8 + s_awqi_output(i,k) = 0._r8 + s_awu_output(i,k) = 0._r8 + s_awv_output(i,k) = 0._r8 + mf_thlflx_output(i,k) = 0._r8 + mf_qtflx_output(i,k) = 0._r8 + end do + end do + end if + + ! Define the grid box size. CLUBB needs this information to determine what ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids @@ -3090,22 +3086,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) enddo - ! At each CLUBB call, initialize mean momentum and thermo CLUBB state - ! from the CAM state - do k = 1, pver - do i = 1, ncol - - rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) - rvm(i,k) = state1%q(i,k,ixq) - um(i,k) = state1%u(i,k) - vm(i,k) = state1%v(i,k) - thlm(i,k) = ( state1%t(i,k) & - - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & - * inv_exner_clubb(i,k) - - enddo - enddo - if (clubb_do_adv) then if (macmic_it == 1) then @@ -3151,21 +3131,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - - do i = 1, ncol - rtm(i,pverp) = rtm(i,pver) - um(i,pverp) = state1%u(i,pver) - vm(i,pverp) = state1%v(i,pver) - thlm(i,pverp) = thlm(i,pver) - end do - - ! Compute virtual potential temperature, which is needed for CLUBB - do k = 1, pver - do i = 1, ncol - thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& - -state1%q(i,k,ixcldliq)) - enddo - enddo call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) @@ -3175,7 +3140,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call tropopause_findChemTrop( state, troplev ) - ! Define the CLUBB momentum grid (in height, units of m) do k=1, nzm_clubb do i=1, ncol @@ -3183,33 +3147,43 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Define the CLUBB thermodynamic grid (in units of m) - do k=1, nzt_clubb - do i=1, ncol - zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) - end do - end do - - ! Thermodynamic ghost point is below surface - do i=1, ncol - zt_g(i,1) = -1._r8*zt_g(i,2) - end do - do k=1, pver do i=1, ncol + + ! Compute virtual potential temperature, which is needed for CLUBB + thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& + -state1%q(i,k,ixcldliq)) + dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness - end do - end do - do i=1, ncol - ! Set the elevation of the surface - sfc_elevation(i) = state1%zi(i,pver+1) + ! At each CLUBB call, initialize mean momentum and thermo CLUBB state + ! from the CAM state + rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) + rvm(i,k) = state1%q(i,k,ixq) + um(i,k) = state1%u(i,k) + vm(i,k) = state1%v(i,k) + thlm(i,k) = ( state1%t(i,k) & + - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & + * inv_exner_clubb(i,k) + + enddo + enddo + + do i = 1, ncol + rtm(i,pverp) = rtm(i,pver) + um(i,pverp) = state1%u(i,pver) + vm(i,pverp) = state1%v(i,pver) + thlm(i,pverp) = thlm(i,pver) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core do k = 1, nzt_clubb do i = 1, ncol + + ! Define the CLUBB thermodynamic grid (in units of m) + zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) + ! base state (dry) variables rho_ds_zt(i,k+1) = rga*(state1%pdeldry(i,pver-k+1)/dz_g(i,pver-k+1)) invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) @@ -3247,6 +3221,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & radf(i,1) = radf(i,2) qrl_clubb(i,1) = qrl_clubb(i,2) wm_zt(i,1) = wm_zt(i,2) + zt_g(i,1) = -1._r8*zt_g(i,2) + + ! Set the elevation of the surface + sfc_elevation(i) = state1%zi(i,pverp) end do @@ -3333,11 +3311,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) ! Zero out SILHS covariance contribution terms - rtp2_mc_zt(:,:) = 0.0_r8 - thlp2_mc_zt(:,:) = 0.0_r8 - wprtp_mc_zt(:,:) = 0.0_r8 - wpthlp_mc_zt(:,:) = 0.0_r8 - rtpthlp_mc_zt(:,:) = 0.0_r8 + do k = 1, pverp + do i = 1, pcols + rtp2_mc_zt(i,k) = 0.0_r8 + thlp2_mc_zt(i,k) = 0.0_r8 + wprtp_mc_zt(i,k) = 0.0_r8 + wpthlp_mc_zt(i,k) = 0.0_r8 + rtpthlp_mc_zt(i,k) = 0.0_r8 + end do + end do ! Compute some inputs from the thermodynamic grid @@ -3358,6 +3340,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Implementation after Thomas Toniazzo (NorESM) and Colin Zarzycki (PSU) ! Other Surface fluxes provided by host model if( (cld_macmic_num_steps > 1) .and. clubb_l_intr_sfc_flux_smooth ) then + ! Adjust surface stresses using winds from the prior macmic iteration do i=1,ncol ubar = sqrt(state1%u(i,pver)**2+state1%v(i,pver)**2) @@ -3524,6 +3507,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_l_do_expldiff_rtm_thlm) then + do k=1,nzt_clubb do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) @@ -3757,7 +3741,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call endrun(subr//': Fatal error in CLUBB library') end if - if (do_rainturb) then + if ( do_rainturb ) then do k=1,nzm_clubb do i=1,ncol @@ -3923,39 +3907,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - call t_stopf('clubb_tend_cam:flip-index') - call t_startf('clubb_tend_cam:NAR') - - ! Accumulate vars through macmic subcycle - upwp_clubb_gw_mc(:ncol,:) = upwp_clubb_gw_mc(:ncol,:) + upwp(:ncol,:) - vpwp_clubb_gw_mc(:ncol,:) = vpwp_clubb_gw_mc(:ncol,:) + vpwp(:ncol,:) - thlp2_clubb_gw_mc(:ncol,:) = thlp2_clubb_gw_mc(:ncol,:) + thlp2(:ncol,:) - wpthlp_clubb_gw_mc(:ncol,:) = wpthlp_clubb_gw_mc(:ncol,:) + wpthlp(:ncol,:) - - ! And average at last macmic step - if (macmic_it == cld_macmic_num_steps) then - upwp_clubb_gw(:ncol,:) = upwp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - vpwp_clubb_gw(:ncol,:) = vpwp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - thlp2_clubb_gw(:ncol,:) = thlp2_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - wpthlp_clubb_gw(:ncol,:) = wpthlp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - end if - - do k=1, nzm_clubb - do i=1, ncol - - mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * pdf_params_chnk(lchnk)%rt_1(i,k) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * pdf_params_chnk(lchnk)%rt_2(i,k) - - pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) - end do - end do do ixind=1,edsclr_dim do k=1, nzm_clubb @@ -3997,9 +3948,50 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if - ! Values to use above top_lev, for variables that have not already been - ! set up there. These are mostly fill values that should not actually be - ! used in the run, but may end up in diagnostic output. + call t_stopf('clubb_tend_cam:flip-index') + + + call t_startf('clubb_tend_cam:NAR') + do k=1, pverp + do i=1, ncol + + ! Accumulate vars through macmic subcycle + upwp_clubb_gw_mc(i,k) = upwp_clubb_gw_mc(i,k) + upwp(i,k) + vpwp_clubb_gw_mc(i,k) = vpwp_clubb_gw_mc(i,k) + vpwp(i,k) + thlp2_clubb_gw_mc(i,k) = thlp2_clubb_gw_mc(i,k) + thlp2(i,k) + wpthlp_clubb_gw_mc(i,k) = wpthlp_clubb_gw_mc(i,k) + wpthlp(i,k) + + ! And average at last macmic step + if (macmic_it == cld_macmic_num_steps) then + upwp_clubb_gw(i,k) = upwp_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + vpwp_clubb_gw(i,k) = vpwp_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + thlp2_clubb_gw(i,k) = thlp2_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + wpthlp_clubb_gw(i,k) = wpthlp_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + end if + + end do + end do + + do k=1, nzm_clubb + do i=1, ncol + + mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * pdf_params_chnk(lchnk)%rt_1(i,k) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * pdf_params_chnk(lchnk)%rt_2(i,k) + + pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) + end do + end do + + ! Values to use above top_lev, for variables that have not already been + ! set up there. These are mostly fill values that should not actually be + ! used in the run, but may end up in diagnostic output. do k=1, top_lev-1 do i=1, ncol upwp(i,k) = 0._r8 @@ -4015,23 +4007,27 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! Fill up arrays needed for McICA. Note we do not want the ghost point, + ! thus why the second loop is needed. + do i=1, pcols + zi_out(i,1) = 0._r8 + end do + ! enforce zero tracer tendencies above the top_lev level -- no change icnt=0 do ixind=1,pcnst if (lq(ixind)) then icnt=icnt+1 - do i=1, ncol - edsclr_out(i,:top_lev-1,icnt) = state1%q(i,:top_lev-1,ixind) + do k=1, top_lev-1 + do i=1, ncol + edsclr_out(i,k,icnt) = state1%q(i,k,ixind) + end do end do end if end do - ! Fill up arrays needed for McICA. Note we do not want the ghost point, - ! thus why the second loop is needed. - zi_out(:,1) = 0._r8 - ! Compute static energy using CLUBB's variables do k=1,pver do i=1, ncol @@ -4059,16 +4055,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_set_field(pbuf, clubbtop_idx, clubbtop) endif + do i=1, ncol + se_a(i) = 0._r8 + ke_a(i) = 0._r8 + wv_a(i) = 0._r8 + wl_a(i) = 0._r8 + + se_b(i) = 0._r8 + ke_b(i) = 0._r8 + wv_b(i) = 0._r8 + wl_b(i) = 0._r8 + end do - ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water - ! after CLUBB is called. This is for energy conservation purposes. - se_a(:) = 0._r8 - ke_a(:) = 0._r8 - wv_a(:) = 0._r8 - wl_a(:) = 0._r8 - - do k=1,pver - do i=1, ncol + ! NO COLLAPSE(2) + do i=1, ncol + do k=1,pver + ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water + ! after CLUBB is called. This is for energy conservation purposes. se_a(i) = se_a(i) + clubb_s(i,k)*state1%pdel(i,k)*rga ke_a(i) = ke_a(i) + 0.5_r8*(um(i,k)**2+vm(i,k)**2)*state1%pdel(i,k)*rga wv_a(i) = wv_a(i) + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga @@ -4076,14 +4079,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Do the same as above, but for before CLUBB was called. - se_b(:) = 0._r8 - ke_b(:) = 0._r8 - wv_b(:) = 0._r8 - wl_b(:) = 0._r8 - - do k=1, pver - do i=1, ncol + ! NO COLLAPSE(2) + do i=1, ncol + do k=1, pver + ! Do the same as above, but for before CLUBB was called. se_b(i) = se_b(i) + state1%s(i,k)*state1%pdel(i,k)*rga ke_b(i) = ke_b(i) + 0.5_r8*(state1%u(i,k)**2+state1%v(i,k)**2)*state1%pdel(i,k)*rga wv_b(i) = wv_b(i) + state1%q(i,k,ixq)*state1%pdeldry(i,k)*rga @@ -4125,34 +4124,45 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Now compute the tendencies of CLUBB to CAM, note that pverp is the ghost point ! for all variables and therefore is never called in this loop - rtm_integral_vtend(:) = 0._r8 - rtm_integral_ltend(:) = 0._r8 + do i=1, ncol + end do - do k=1, pver - do i=1, ncol + ! NO COLLAPSE(2) + do i=1, ncol - ptend_loc%u(i,k) = (um(i,k) - state1%u(i,k)) / hdtime ! east-west wind - ptend_loc%v(i,k) = (vm(i,k) - state1%v(i,k)) / hdtime ! north-south wind - ptend_loc%q(i,k,ixq) = (rtm(i,k) - rcm(i,k)-state1%q(i,k,ixq)) / hdtime ! water vapor - ptend_loc%q(i,k,ixcldliq) = (rcm(i,k) - state1%q(i,k,ixcldliq)) / hdtime ! Tendency of liquid water - ptend_loc%s(i,k) = (clubb_s(i,k) - state1%s(i,k)) / hdtime ! Tendency of static energy + rtm_integral_vtend(i) = 0._r8 + rtm_integral_ltend(i) = 0._r8 - rtm_integral_ltend(i) = rtm_integral_ltend(i) + ptend_loc%q(i,k,ixcldliq)*state1%pdel(i,k) - rtm_integral_vtend(i) = rtm_integral_vtend(i) + ptend_loc%q(i,k,ixq)*state1%pdel(i,k) + do k=1, pver - end do - end do + ptend_loc%u(i,k) = (um(i,k) - state1%u(i,k)) / hdtime ! east-west wind + ptend_loc%v(i,k) = (vm(i,k) - state1%v(i,k)) / hdtime ! north-south wind + ptend_loc%q(i,k,ixq) = (rtm(i,k) - rcm(i,k)-state1%q(i,k,ixq)) / hdtime ! water vapor + ptend_loc%q(i,k,ixcldliq) = (rcm(i,k) - state1%q(i,k,ixcldliq)) / hdtime ! Tendency of liquid water + ptend_loc%s(i,k) = (clubb_s(i,k) - state1%s(i,k)) / hdtime ! Tendency of static energy + + rtm_integral_ltend(i) = rtm_integral_ltend(i) + ptend_loc%q(i,k,ixcldliq)*state1%pdel(i,k) + rtm_integral_vtend(i) = rtm_integral_vtend(i) + ptend_loc%q(i,k,ixq)*state1%pdel(i,k) + + end do - rtm_integral_ltend(:) = rtm_integral_ltend(:)/gravit - rtm_integral_vtend(:) = rtm_integral_vtend(:)/gravit + rtm_integral_ltend(i) = rtm_integral_ltend(i)/gravit + rtm_integral_vtend(i) = rtm_integral_vtend(i)/gravit + + end do ! Accumulate Air Temperature Tendency (TTEND) for Gravity Wave parameterization - ttend_clubb_mc(:ncol,:pver) = ttend_clubb_mc(:ncol,:pver) + ptend_loc%s(:ncol,:pver)/cpair + do k=1, pver + do i=1, ncol + ttend_clubb_mc(i,k) = ttend_clubb_mc(i,k) + ptend_loc%s(i,k)/cpair - ! Average at last macmic step - if (macmic_it == cld_macmic_num_steps) then - ttend_clubb(:ncol,:) = ttend_clubb_mc(:ncol,:pver)/REAL(cld_macmic_num_steps,r8) - end if + ! Average at last macmic step + if (macmic_it == cld_macmic_num_steps) then + ttend_clubb(i,k) = ttend_clubb_mc(i,k) / REAL(cld_macmic_num_steps,r8) + end if + + end do + end do if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -4181,6 +4191,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! Add constant to ghost point so that output is not corrupted + wp3(:,pverp) = wp3(:,pverp) + wp3_const + rtpthlp(:,pverp) = rtpthlp(:,pverp) + rtpthlp_const + wpthlp(:,pverp) = wpthlp(:,pverp) + wpthlp_const + wprtp(:,pverp) = wprtp(:,pverp) + wprtp_const + else do k=1, pver @@ -4231,16 +4247,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) - ! Add constant to ghost point so that output is not corrupted - if (clubb_do_adv) then - if (macmic_it == cld_macmic_num_steps) then - wp3(:,pverp) = wp3(:,pverp) + wp3_const - rtpthlp(:,pverp) = rtpthlp(:,pverp) + rtpthlp_const - wpthlp(:,pverp) = wpthlp(:,pverp) + wpthlp_const - wprtp(:,pverp) = wprtp(:,pverp) + wprtp_const - end if - end if - ! ------------------------------------------------- ! ! End column computation of CLUBB, begin to apply ! ! and compute output, etc ! @@ -4392,6 +4398,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water + ! output moist basis to be consistent with history variable definition temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) From 7b94963d8eb455e4f36cd93b68c5a622b34f16e8 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Mon, 14 Oct 2024 12:13:22 -0600 Subject: [PATCH 06/89] Some GPUization. --- src/physics/cam/clubb_intr.F90 | 274 ++++++++++++++++++--------------- 1 file changed, 150 insertions(+), 124 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 42e41c6e35..ca1aa2b215 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3360,9 +3360,108 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif call t_stopf('clubb_tend_cam:NAR') + + call t_startf('clubb_tend_cam:acc_copyin') + + + !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & + !$acc gr%weights_zt2zm, gr%weights_zm2zt, & + !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & + !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & + !$acc nu_vert_res_dep%nu6, & + !$acc sclr_idx, clubb_params, & + !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & + !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, & + !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & + !$acc vm_ref, ug, vg, grid_dx, grid_dy, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & + !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc state1, state1%q, state1%pint ) & + !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & + !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & + !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & + !$acc rcm_inout, pdf_params_zm_chnk, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & + !$acc invrs_exner_zm, edsclr_in, rcm_in_layer_out, cloud_cover_out, zt_g, zi_g, khzm_out, & + !$acc qclvar_out, wm_zt, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out, khzt_out, thlprcp_out, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & + !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & + !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & + !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, edsclr_out, pdfp_rtp2, wprcp_out ) + + !$acc data if( sclr_dim > 0 ) & + !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & + !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & + !$acc copy( edsclr_in ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & + !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') + + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol @@ -3395,17 +3494,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_inout(i,k) = state1%q(i,pverp-k+1,ixcldliq) end if - ! We only need to copy pdf_params from pbuf if this is a restart and - ! we're calling pdf_closure at the end of advance_clubb_core - if ( is_first_restart_step() & - .and. clubb_config_flags%ipdf_call_placement .eq. ipdf_post_advance_fields ) then - pdf_params_zm_chnk(lchnk)%w_1(i,k) = pdf_zm_w_1(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%w_2(i,k) = pdf_zm_w_2(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%varnce_w_1(i,k) = pdf_zm_varnce_w_1(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%varnce_w_2(i,k) = pdf_zm_varnce_w_2(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%mixt_frac(i,k) = pdf_zm_mixt_frac(i,pverp-k+1) - end if - wp2rtp_inout(i,k) = wp2rtp(i,pverp-k+1) wp2thlp_inout(i,k) = wp2thlp(i,pverp-k+1) uprcp_inout(i,k) = uprcp(i,pverp-k+1) @@ -3420,12 +3508,30 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! We only need to copy pdf_params from pbuf if this is a restart and + ! we're calling pdf_closure at the end of advance_clubb_core + if ( is_first_restart_step() & + .and. clubb_config_flags%ipdf_call_placement .eq. ipdf_post_advance_fields ) then + !$acc parallel loop gang vector collapse(2) default(present) + do k = 1, nzm_clubb + do i = 1, ncol + pdf_params_zm_chnk(lchnk)%w_1(i,k) = pdf_zm_w_1(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%w_2(i,k) = pdf_zm_w_2(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%varnce_w_1(i,k) = pdf_zm_varnce_w_1(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%varnce_w_2(i,k) = pdf_zm_varnce_w_2(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%mixt_frac(i,k) = pdf_zm_mixt_frac(i,pverp-k+1) + end do + end do + end if + + !$acc parallel loop gang vector collapse(2) default(present) do k=2, nzm_clubb do i=1,ncol pre_in(i,k) = prer_evap(i,pverp-k+1) end do end do + !$acc parallel loop gang vector default(present) do i=1,ncol pre_in(i,1) = pre_in(i,2) rcm_inout(i,1) = rcm_inout(i,2) @@ -3492,12 +3598,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & icnt = icnt+1 + !$acc parallel loop gang vector collapse(2) default(present) do k=1,nzt_clubb do i=1,ncol edsclr_in(i,k+1,icnt) = state1%q(i,pver-k+1,ixind) end do end do + !$acc parallel loop gang vector default(present) do i=1,ncol edsclr_in(i,1,icnt) = edsclr_in(i,2,icnt) end do @@ -3508,6 +3616,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_l_do_expldiff_rtm_thlm) then + !$acc parallel loop gang vector collapse(2) default(present) do k=1,nzt_clubb do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) @@ -3515,6 +3624,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + !$acc parallel loop gang vector default(present) do i=1, ncol edsclr_in(i,1,icnt+1) = edsclr_in(i,2,icnt+1) edsclr_in(i,1,icnt+2) = edsclr_in(i,2,icnt+2) @@ -3524,94 +3634,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:flip-index') - - call t_startf('clubb_tend_cam:acc_copyin') - !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & - !$acc gr%weights_zt2zm, gr%weights_zm2zt, & - !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & - !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & - !$acc nu_vert_res_dep%nu6, & - !$acc sclr_idx, clubb_params, & - !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & - !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & - !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & - !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, & - !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & - !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & - !$acc vm_ref, ug, vg, grid_dx, grid_dy, & - !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk) ) & - !$acc copy( um_in, upwp_in, vm_in, vpwp_in, up2_in, vp2_in, up3_in, vp3_in, rtm_in, & - !$acc wprtp_in, thlm_in, wpthlp_in, rtp2_in, & - !$acc rtp3_in, thlp2_in, thlp3_in, rtpthlp_in, wp2_in, wp3_in, & - !$acc p_in_Pa, exner, rcm_inout, cloud_frac_inout, wpthvp_in, wp2thvp_in, & - !$acc rtpthvp_in, thlpthvp_in, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & - !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & - !$acc ice_supersat_frac_inout, um_pert_inout, & - !$acc vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & - !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & - !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & - !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & - !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & - !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & - !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & - !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & - !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & - !$acc copyout( rcm_in_layer_out, cloud_cover_out, wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & - !$acc cloudy_updraft_frac_out, cloudy_downdraft_frac_out, invrs_tau_zm_out, khzt_out, & - !$acc khzm_out, thlprcp_out, qclvar_out ) - - !$acc data if( sclr_dim > 0 ) & - !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & - !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) - - !$acc data if( edsclr_dim > 0 ) & - !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in ) - - !$acc data if( hydromet_dim > 0 ) & - !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & - !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) - call t_stopf('clubb_tend_cam:acc_copyin') - do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3807,13 +3829,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo ! end time loop call t_startf('clubb_tend_cam:NAR') - call t_startf('clubb_tend_cam:acc_copyout') - !$acc end data - !$acc end data - !$acc end data - !$acc end data - call t_stopf('clubb_tend_cam:acc_copyout') - if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -3848,7 +3863,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') + ! Arrays need to be "flipped" to CAM grid + !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol um(i,pverp-k+1) = um_in(i,k) @@ -3909,6 +3926,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do do ixind=1,edsclr_dim + !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) @@ -3948,9 +3966,35 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if + !$acc parallel loop gang vector collapse(2) default(present) + do k=1, nzm_clubb + do i=1, ncol + + mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * pdf_params_chnk(lchnk)%rt_1(i,k) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * pdf_params_chnk(lchnk)%rt_2(i,k) + + pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) + end do + end do + call t_stopf('clubb_tend_cam:flip-index') + call t_startf('clubb_tend_cam:acc_copyout') + !$acc end data + !$acc end data + !$acc end data + !$acc end data + call t_stopf('clubb_tend_cam:acc_copyout') + + call t_startf('clubb_tend_cam:NAR') do k=1, pverp do i=1, ncol @@ -3972,23 +4016,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - do k=1, nzm_clubb - do i=1, ncol - - mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * pdf_params_chnk(lchnk)%rt_1(i,k) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * pdf_params_chnk(lchnk)%rt_2(i,k) - - pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) - end do - end do - ! Values to use above top_lev, for variables that have not already been ! set up there. These are mostly fill values that should not actually be ! used in the run, but may end up in diagnostic output. @@ -4398,7 +4425,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water - ! output moist basis to be consistent with history variable definition temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) From 7786ccaad5104b528bd0a26871c3d9772c4f0ec9 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 14:13:59 -0600 Subject: [PATCH 07/89] Small bug fixes --- src/physics/cam/clubb_intr.F90 | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index ca1aa2b215..1c8498a2a7 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2897,9 +2897,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert(i) = 0.0_r8 vpwp_sfc_pert(i) = 0.0_r8 - - ! higher order scalar stuff, put to zero - wpsclrp_sfc(i,sclr) = 0._r8 end do ! higher order scalar stuff, put to zero @@ -2917,6 +2914,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + do sclr = 1, sclr_dim + do i=1, ncol + wpsclrp_sfc(i,sclr) = 0._r8 + end do + end do + do ixind=1, hydromet_dim do k=1, nzm_clubb do i=1, ncol @@ -2931,7 +2934,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Initialize forcings for transported scalars to zero do sclr = 1, sclr_dim - do i = 1, pcols + do i = 1, ncol do k = 1, nzm_clubb sclrm_forcing(i,k,sclr) = 0._r8 sclrm(i,k,sclr) = 0._r8 @@ -2940,7 +2943,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do do edsclr = 1, edsclr_dim - do i = 1, pcols + do i = 1, ncol do k = 1, nzm_clubb edsclrm_forcing(i,k,edsclr) = 0._r8 edsclr_in(i,k,edsclr) = 0._r8 @@ -3380,11 +3383,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc vm_ref, ug, vg, grid_dx, grid_dy, & !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, state1%pint ) & + !$acc state1, state1%q, state1%pint, prer_evap ) & !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & - !$acc rcm_inout, pdf_params_zm_chnk, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & !$acc invrs_exner_zm, edsclr_in, rcm_in_layer_out, cloud_cover_out, zt_g, zi_g, khzm_out, & From 0d391b1b0a59dd80a5dfaff8a67b804b01b6d0ed Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 15:40:48 -0600 Subject: [PATCH 08/89] Tweaks to acc data statement. This version passed the GPU ect test. --- src/physics/cam/clubb_intr.F90 | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 1c8498a2a7..e1c6d506cb 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3383,16 +3383,25 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc vm_ref, ug, vg, grid_dx, grid_dy, & !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, state1%pint, prer_evap ) & + !$acc state1, state1%q, prer_evap ) & !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & - !$acc invrs_exner_zm, edsclr_in, rcm_in_layer_out, cloud_cover_out, zt_g, zi_g, khzm_out, & - !$acc qclvar_out, wm_zt, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & - !$acc w_down_in_cloud_out, invrs_tau_zm_out, khzt_out, thlprcp_out, & + !$acc invrs_exner_zm, & + !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & + !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & + !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & + !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & + !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & + !$acc zi_g, zt_g, & !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & @@ -3438,14 +3447,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & - !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & - !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & - !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & - !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & - !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & - !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & - !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, edsclr_out, pdfp_rtp2, wprcp_out ) + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) !$acc data if( sclr_dim > 0 ) & !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & @@ -3453,7 +3455,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc data if( edsclr_dim > 0 ) & !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in ) + !$acc copy( edsclr_in, edsclr_out ) !$acc data if( hydromet_dim > 0 ) & !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & @@ -3817,7 +3819,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:do_cldcool') end if - + ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (stats_metadata%l_stats) then From cf5883468a10760b7e33e377e75fbb73b9c4b78a Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 22:42:06 -0600 Subject: [PATCH 09/89] More GPUization and small changes. ECT passed on CPU and GPU. --- src/physics/cam/clubb_intr.F90 | 391 +++++++++++++++++---------------- 1 file changed, 206 insertions(+), 185 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index e1c6d506cb..c7c5ad80b2 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2590,7 +2590,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & nzm_clubb, & nzt_clubb, & sclr, & - edsclr + edsclr, & + n #endif @@ -2606,6 +2607,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if ( do_clubb_mf ) call endrun(subr//': do_clubb_mf=.true. not available when compiling with OpenACC') if ( do_rainturb ) call endrun(subr//': do_rainturb=.true. not available when compiling with OpenACC') if ( do_cldcool ) call endrun(subr//': do_cldcool=.true. not available when compiling with OpenACC') + if ( clubb_do_icesuper ) call endrun(subr//': clubb_do_icesuper=.true. not available when compiling with OpenACC') + if ( single_column .and. .not. scm_cambfb_mode ) then + call endrun(subr//': (single_column && !scm_cambfb_mode)=.true. not available when compiling with OpenACC') + end if #endif !-----------------------------------------------------------------------------------! @@ -2732,6 +2737,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_liqsupersat) then call pbuf_get_field(pbuf, npccn_idx, npccn) endif + + ! Define the grid box size. CLUBB needs this information to determine what + ! the maximum length scale should be. This depends on the column for + ! variable mesh grids and lat-lon grids + call grid_size(state1, grid_dx, grid_dy) @@ -2834,11 +2844,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ztodtptr(:) = 1.0_r8*hdtime - ! Determine Coriolis force at given latitude. This is never used - ! when CLUBB is implemented in a host model, therefore just set - ! to zero. - fcor(:) = 0._r8 - call t_startf('clubb_tend_cam:NAR') do k = 1, pverp @@ -2897,6 +2902,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert(i) = 0.0_r8 vpwp_sfc_pert(i) = 0.0_r8 + + ! Determine Coriolis force at given latitude. This is never used + ! when CLUBB is implemented in a host model, therefore just set + ! to zero. + fcor(i) = 0._r8 end do ! higher order scalar stuff, put to zero @@ -2910,10 +2920,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclrprtp(i,k,sclr) = 0._r8 sclrpthlp(i,k,sclr) = 0._r8 sclrpthvp_inout(i,k,sclr) = 0._r8 + sclrm_forcing(i,k,sclr) = 0._r8 end do end do end do - + do sclr = 1, sclr_dim do i=1, ncol wpsclrp_sfc(i,sclr) = 0._r8 @@ -2932,16 +2943,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Initialize forcings for transported scalars to zero - do sclr = 1, sclr_dim - do i = 1, ncol - do k = 1, nzm_clubb - sclrm_forcing(i,k,sclr) = 0._r8 - sclrm(i,k,sclr) = 0._r8 - end do - end do - end do - do edsclr = 1, edsclr_dim do i = 1, ncol do k = 1, nzm_clubb @@ -3000,13 +3001,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if - - ! Define the grid box size. CLUBB needs this information to determine what - ! the maximum length scale should be. This depends on the column for - ! variable mesh grids and lat-lon grids - - call grid_size(state1, grid_dx, grid_dy) - call t_stopf('clubb_tend_cam:NAR') if (clubb_do_icesuper) then @@ -3073,22 +3067,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') - ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant - ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent - ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables - ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state - do k=1,pver - do i=1,ncol - inv_exner_clubb(i,k) = 1._r8/((state1%pmid(i,k)/p0_clubb)**(rairv(i,k,lchnk)/cpairv(i,k,lchnk))) - enddo - enddo - - ! Compute exner at the surface for converting the sensible heat fluxes - ! to a flux of potential temperature for use as clubb's boundary conditions - do i=1,ncol - inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) - enddo - if (clubb_do_adv) then if (macmic_it == 1) then @@ -3135,102 +3113,213 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) + call t_startf('clubb_tend_cam:acc_copyin') + !$acc data copyin( sclr_idx, clubb_params, & + !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & + !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, clubb_params_single_col, & + !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & + !$acc vm_ref, ug, vg, grid_dx, grid_dy, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & + !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & + !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & + !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & + !$acc rrho, prer_evap, inv_exner_clubb_surf, & + !$acc rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & + !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & + !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & + !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & + !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & + !$acc invrs_exner_zm, & + !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & + !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & + !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & + !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & + !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & + !$acc zi_g, zt_g, qrl_clubb, qrl, thv, dz_g, radf_clubb, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) - !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists - troplev(:) = 0 - !REMOVECAM_END - call tropopause_findChemTrop( state, troplev ) + !$acc data if( sclr_dim > 0 ) & + !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & + !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & + !$acc copy( edsclr_in, edsclr_out ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & + !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') ! Define the CLUBB momentum grid (in height, units of m) + !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol - zi_g(i,k) = state1%zi(i,pverp-k+1)-state1%zi(i,pver+1) + zi_g(i,k) = state1%zi(i,pverp-k+1) - state1%zi(i,pver+1) end do end do + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pver do i=1, ncol + + ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant + ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent + ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables + ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state + inv_exner_clubb(i,k) = 1._r8/((state1%pmid(i,k)/p0_clubb)**(rairv(i,k,lchnk)/cpairv(i,k,lchnk))) ! Compute virtual potential temperature, which is needed for CLUBB - thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& - -state1%q(i,k,ixcldliq)) + thv(i,k) = state1%t(i,k) * inv_exner_clubb(i,k) & + * ( 1._r8 + zvir * state1%q(i,k,ixq) - state1%q(i,k,ixcldliq) ) - dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness + dz_g(i,k) = state1%zi(i,k) - state1%zi(i,k+1) ! compute thickness ! At each CLUBB call, initialize mean momentum and thermo CLUBB state ! from the CAM state - rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) + rtm(i,k) = state1%q(i,k,ixq) + state1%q(i,k,ixcldliq) rvm(i,k) = state1%q(i,k,ixq) um(i,k) = state1%u(i,k) vm(i,k) = state1%v(i,k) - thlm(i,k) = ( state1%t(i,k) & - - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & + thlm(i,k) = ( state1%t(i,k) - ( latvap / cpairv(i,k,lchnk) ) * state1%q(i,k,ixcldliq) ) & * inv_exner_clubb(i,k) enddo enddo + !$acc parallel loop gang vector default(present) do i = 1, ncol rtm(i,pverp) = rtm(i,pver) um(i,pverp) = state1%u(i,pver) vm(i,pverp) = state1%v(i,pver) thlm(i,pverp) = thlm(i,pver) + + ! Compute exner at the surface for converting the sensible heat fluxes + ! to a flux of potential temperature for use as clubb's boundary conditions + inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzt_clubb do i = 1, ncol ! Define the CLUBB thermodynamic grid (in units of m) - zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) + zt_g(i,k+1) = state1%zm(i,pver-k+1) - state1%zi(i,pver+1) ! base state (dry) variables - rho_ds_zt(i,k+1) = rga*(state1%pdeldry(i,pver-k+1)/dz_g(i,pver-k+1)) - invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) + rho_ds_zt(i,k+1) = rga * ( state1%pdeldry(i,pver-k+1) / dz_g(i,pver-k+1) ) + invrs_rho_ds_zt(i,k+1) = 1._r8 / rho_ds_zt(i,k+1) ! full state (moist) variables p_in_Pa(i,k+1) = state1%pmid(i,pver-k+1) - exner(i,k+1) = 1._r8/inv_exner_clubb(i,pver-k+1) - thv(i,k+1) = state1%t(i,pver-k+1)*inv_exner_clubb(i,pver-k+1)*(1._r8+zvir*state1%q(i,pver-k+1,ixq) & - -state1%q(i,pver-k+1,ixcldliq)) - rho_zt(i,k+1) = rga*state1%pdel(i,pver-k+1)/dz_g(i,pver-k+1) + exner(i,k+1) = 1._r8 / inv_exner_clubb(i,pver-k+1) + thv(i,k+1) = state1%t(i,pver-k+1) * inv_exner_clubb(i,pver-k+1) & + * ( 1._r8 + zvir * state1%q(i,pver-k+1,ixq) - state1%q(i,pver-k+1,ixcldliq) ) + rho_zt(i,k+1) = rga * state1%pdel(i,pver-k+1) / dz_g(i,pver-k+1) ! exception - setting this to moist thv thv_ds_zt(i,k+1) = thv(i,k+1) rfrzm(i,k+1) = state1%q(i,pver-k+1,ixcldice) radf(i,k+1) = radf_clubb(i,pver-k+1) - qrl_clubb(i,k+1) = qrl(i,pver-k+1)/(cpairv(i,k,lchnk)*state1%pdeldry(i,pver-k+1)) + qrl_clubb(i,k+1) = qrl(i,pver-k+1) / ( cpairv(i,k,lchnk) * state1%pdeldry(i,pver-k+1) ) ! Compute mean w wind on thermo grid, convert from omega to w - wm_zt(i,k+1) = -1._r8*(state1%omega(i,pver-k+1)-state1%omega(i,pver))/(rho_zt(i,k+1)*gravit) + wm_zt(i,k+1) = -1._r8 * ( state1%omega(i,pver-k+1) - state1%omega(i,pver) ) & + / (rho_zt(i,k+1) * gravit) end do end do ! Below computes the same stuff for the ghost point. May or may ! not be needed, just to be safe to avoid NaN's + !$acc parallel loop gang vector default(present) do i = 1, ncol - thv_ds_zt(i,1) = thv_ds_zt(i,2) + zt_g(i,1) = -1._r8 * zt_g(i,2) rho_ds_zt(i,1) = rho_ds_zt(i,2) invrs_rho_ds_zt(i,1) = invrs_rho_ds_zt(i,2) p_in_Pa(i,1) = p_in_Pa(i,2) exner(i,1) = exner(i,2) thv(i,1) = thv(i,2) rho_zt(i,1) = rho_zt(i,2) + thv_ds_zt(i,1) = thv_ds_zt(i,2) rfrzm(i,1) = rfrzm(i,2) radf(i,1) = radf(i,2) qrl_clubb(i,1) = qrl_clubb(i,2) wm_zt(i,1) = wm_zt(i,2) - zt_g(i,1) = -1._r8*zt_g(i,2) ! Set the elevation of the surface sfc_elevation(i) = state1%zi(i,pverp) end do + !$acc parallel loop gang vector collapse(2) default(present) + do i = 1, ncol + do n = 1, nparams + clubb_params(i,n) = clubb_params_single_col(n) + end do + end do + + ! ------------------------------------------------- ! ! Begin case specific code for SCAM cases. ! ! This section of code block is NOT called in ! @@ -3289,31 +3378,49 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Important note: do not make any calls that use CLUBB grid-height ! operators (such as zt2zm_api, etc.) until AFTER the ! call to setup_grid_heights_api. + + !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) gr ) ! intent(out) - do i = 1, ncol - clubb_params(i,:) = clubb_params_single_col(:) - end do call setup_parameters_api( zi_g(:,2), clubb_params, gr, ncol, grid_type, & ! intent(in) clubb_config_flags%l_prescribed_avg_deltaz, & ! intent(in) lmin, nu_vert_res_dep, err_code ) ! intent(out) + !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & + !$acc gr%weights_zt2zm, gr%weights_zm2zt, & + !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & + !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & + !$acc nu_vert_res_dep%nu6) + if ( err_code == clubb_fatal_error ) then call endrun(subr//': Fatal error in CLUBB setup_parameters') end if + !$acc parallel loop gang vector collapse(2) default(present) + do k = 1, nzm_clubb + do i = 1, ncol + rtp2_forcing = rtp2_mc_zt(i,k) + thlp2_forcing = thlp2_mc_zt(i,k) + wprtp_forcing = wprtp_mc_zt(i,k) + wpthlp_forcing = wpthlp_mc_zt(i,k) + rtpthlp_forcing = rtpthlp_mc_zt(i,k) + end do + end do + ! Add forcings for SILHS covariance contributions - rtp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtp2_mc_zt(1:ncol,:) ) - thlp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, thlp2_mc_zt(1:ncol,:) ) - wprtp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wprtp_mc_zt(1:ncol,:) ) - wpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wpthlp_mc_zt(1:ncol,:) ) - rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) + rtp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtp2_forcing ) + thlp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, thlp2_forcing ) + wprtp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wprtp_forcing ) + wpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wpthlp_forcing ) + rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_forcing ) ! Zero out SILHS covariance contribution terms + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pverp do i = 1, pcols rtp2_mc_zt(i,k) = 0.0_r8 @@ -3334,6 +3441,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wm_zm = zt2zm_api( nzm_clubb, ncol, gr, wm_zt ) ! Surface fluxes provided by host model + !$acc parallel loop gang vector default(present) do i=1,ncol wpthlp_sfc(i) = cam_in%shf(i)/(cpairv(i,pver,lchnk)*rho_ds_zm(i,1)) ! Sensible heat flux wpthlp_sfc(i) = wpthlp_sfc(i)*inv_exner_clubb_surf(i) ! Potential temperature flux @@ -3344,123 +3452,32 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Other Surface fluxes provided by host model if( (cld_macmic_num_steps > 1) .and. clubb_l_intr_sfc_flux_smooth ) then - ! Adjust surface stresses using winds from the prior macmic iteration - do i=1,ncol - ubar = sqrt(state1%u(i,pver)**2+state1%v(i,pver)**2) - if (ubar < 0.25_r8) ubar = 0.25_r8 - - call calc_ustar( state1%t(i,pver), state1%pmid(i,pver), cam_in%wsx(i), cam_in%wsy(i), & - rrho(i), ustar ) - - upwp_sfc(i) = -state1%u(i,pver)*ustar**2/ubar - vpwp_sfc(i) = -state1%v(i,pver)*ustar**2/ubar - end do - else - do i=1,ncol - upwp_sfc(i) = cam_in%wsx(i)/rho_ds_zm(i,1) ! Surface meridional momentum flux - vpwp_sfc(i) = cam_in%wsy(i)/rho_ds_zm(i,1) ! Surface zonal momentum flux - end do - endif - call t_stopf('clubb_tend_cam:NAR') + !$acc update host( state1%u, state1%v, state1%t, state1%pmid, cam_in%wsx, cam_in%wsy, rrho ) + ! Adjust surface stresses using winds from the prior macmic iteration + do i=1,ncol + ubar = sqrt(state1%u(i,pver)**2+state1%v(i,pver)**2) + if (ubar < 0.25_r8) ubar = 0.25_r8 - call t_startf('clubb_tend_cam:acc_copyin') + call calc_ustar( state1%t(i,pver), state1%pmid(i,pver), cam_in%wsx(i), cam_in%wsy(i), & + rrho(i), ustar ) + upwp_sfc(i) = -state1%u(i,pver)*ustar**2/ubar + vpwp_sfc(i) = -state1%v(i,pver)*ustar**2/ubar + end do - !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & - !$acc gr%weights_zt2zm, gr%weights_zm2zt, & - !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & - !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & - !$acc nu_vert_res_dep%nu6, & - !$acc sclr_idx, clubb_params, & - !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & - !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & - !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & - !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, & - !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & - !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & - !$acc vm_ref, ug, vg, grid_dx, grid_dy, & - !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & - !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, prer_evap ) & - !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & - !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & - !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & - !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & - !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & - !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & - !$acc invrs_exner_zm, & - !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & - !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & - !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & - !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & - !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & - !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & - !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & - !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & - !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & - !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & - !$acc zi_g, zt_g, & - !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & - !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & - !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & - !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & - !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & - !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & - !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & - !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & - !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) + !$acc update device( upwp_sfc, vpwp_sfc ) - !$acc data if( sclr_dim > 0 ) & - !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & - !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + else - !$acc data if( edsclr_dim > 0 ) & - !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in, edsclr_out ) + !$acc parallel loop gang vector default(present) + do i=1,ncol + upwp_sfc(i) = cam_in%wsx(i)/rho_ds_zm(i,1) ! Surface meridional momentum flux + vpwp_sfc(i) = cam_in%wsy(i)/rho_ds_zm(i,1) ! Surface zonal momentum flux + end do - !$acc data if( hydromet_dim > 0 ) & - !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & - !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) - call t_stopf('clubb_tend_cam:acc_copyin') + endif + call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') @@ -3997,6 +4014,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc end data !$acc end data !$acc end data + !$acc end data call t_stopf('clubb_tend_cam:acc_copyout') @@ -4154,12 +4172,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif + call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) + ! Now compute the tendencies of CLUBB to CAM, note that pverp is the ghost point ! for all variables and therefore is never called in this loop - do i=1, ncol - end do - - ! NO COLLAPSE(2) do i=1, ncol rtm_integral_vtend(i) = 0._r8 @@ -4585,6 +4601,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! use the aist_vector function to compute the ice cloud fraction ! ! --------------------------------------------------------------------------------- ! + !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists + troplev(:) = 0 + !REMOVECAM_END + call tropopause_findChemTrop( state, troplev ) + aist(:,:top_lev-1) = 0._r8 qsatfac(:, :) = 0._r8 ! Zero out entire profile in case qsatfac is left undefined in aist_vector below From e39e8a37f17ad0c3de2beb188ed51ccb5caaa3a1 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 23:57:23 -0600 Subject: [PATCH 10/89] Bug fix that scarily did not break the CPU ECT test, but was detected by breaking BFBness. All these values are ~0 but not always exactly. --- src/physics/cam/clubb_intr.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index c7c5ad80b2..a5523211cb 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3404,11 +3404,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol - rtp2_forcing = rtp2_mc_zt(i,k) - thlp2_forcing = thlp2_mc_zt(i,k) - wprtp_forcing = wprtp_mc_zt(i,k) - wpthlp_forcing = wpthlp_mc_zt(i,k) - rtpthlp_forcing = rtpthlp_mc_zt(i,k) + rtp2_forcing(i,k) = rtp2_mc_zt(i,k) + thlp2_forcing(i,k) = thlp2_mc_zt(i,k) + wprtp_forcing(i,k) = wprtp_mc_zt(i,k) + wpthlp_forcing(i,k) = wpthlp_mc_zt(i,k) + rtpthlp_forcing(i,k) = rtpthlp_mc_zt(i,k) end do end do From e5e81fb630581140b73edad8d4bab39cceffcee1 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Wed, 16 Oct 2024 01:56:03 -0600 Subject: [PATCH 11/89] More GPUization. ECT passes for CPU and GPU, CPU is BFB. --- src/physics/cam/clubb_intr.F90 | 326 +++++++++++++++++---------------- 1 file changed, 170 insertions(+), 156 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index a5523211cb..a12002e51b 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2844,8 +2844,101 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ztodtptr(:) = 1.0_r8*hdtime + call t_startf('clubb_tend_cam:acc_copyin') + !$acc data copyin( sclr_idx, clubb_params_single_col, grid_dx, grid_dy, rairv, cpairv, radf_clubb, qrl, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & + !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & + !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & + !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & + !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac ) & + !$acc copyout( temp2d, temp2dp, rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wm_zt_out, inv_exner_clubb, & + !$acc rcm, wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, thv, dz_g ) & + !$acc create( upwp_sfc_pert, vpwp_sfc_pert, khzt_out, khzm_out, & + !$acc fcor, um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & + !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & + !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & + !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & + !$acc invrs_exner_zm, cloud_cover_out, rcm_in_layer_out, wprcp_out, & + !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc thlm_forcing, rtm_forcing, um_forcing, vm_forcing, & + !$acc wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, clubb_params, sfc_elevation, wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc rtm_ref, thlm_ref, um_ref, vm_ref, ug, vg, p_in_Pa, exner, um_pert_inout, & + !$acc inv_exner_clubb_surf, thlprcp_out, zi_g, zt_g, qrl_clubb, & + !$acc pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, pdf_zm_mixt_frac, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) + + !$acc data if( sclr_dim > 0 ) & + !$acc create( wpsclrp_sfc, sclrm_forcing, sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout) & + !$acc copyin( sclr_tol ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc create( wpedsclrp_sfc, edsclrm_forcing, edsclr_in ) & + !$acc copyout( edsclr_out ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc create( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt ) & + !$acc copyin( hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') + + call t_startf('clubb_tend_cam:NAR') + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pverp do i = 1, pcols rtp2_zt_out(i,k) = 0._r8 @@ -2858,6 +2951,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pver do i = 1, pcols temp2d(i,k) = 0._r8 @@ -2865,6 +2959,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol @@ -2898,6 +2993,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + !$acc parallel loop gang vector default(present) do i = 1, ncol ! Perturbed winds are not used in CAM upwp_sfc_pert(i) = 0.0_r8 @@ -2909,64 +3005,66 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & fcor(i) = 0._r8 end do - ! higher order scalar stuff, put to zero - do sclr = 1, sclr_dim - do k = 1, nzm_clubb - do i=1, ncol - sclrm(i,k,sclr) = 0._r8 - wpsclrp(i,k,sclr) = 0._r8 - sclrp2(i,k,sclr) = 0._r8 - sclrp3(i,k,sclr) = 0._r8 - sclrprtp(i,k,sclr) = 0._r8 - sclrpthlp(i,k,sclr) = 0._r8 - sclrpthvp_inout(i,k,sclr) = 0._r8 - sclrm_forcing(i,k,sclr) = 0._r8 + if ( sclr_dim > 0 ) then + ! higher order scalar stuff, put to zero + !$acc parallel loop gang vector collapse(3) default(present) + do sclr = 1, sclr_dim + do k = 1, nzm_clubb + do i=1, ncol + sclrm(i,k,sclr) = 0._r8 + wpsclrp(i,k,sclr) = 0._r8 + sclrp2(i,k,sclr) = 0._r8 + sclrp3(i,k,sclr) = 0._r8 + sclrprtp(i,k,sclr) = 0._r8 + sclrpthlp(i,k,sclr) = 0._r8 + sclrpthvp_inout(i,k,sclr) = 0._r8 + sclrm_forcing(i,k,sclr) = 0._r8 + end do end do end do - end do - - do sclr = 1, sclr_dim - do i=1, ncol - wpsclrp_sfc(i,sclr) = 0._r8 - end do - end do - - do ixind=1, hydromet_dim - do k=1, nzm_clubb + + !$acc parallel loop gang vector collapse(2) default(present) + do sclr = 1, sclr_dim do i=1, ncol - hydromet(i,k,ixind) = 0._r8 - wphydrometp(i,k,ixind) = 0._r8 - wp2hmp(i,k,ixind) = 0._r8 - rtphmp_zt(i,k,ixind) = 0._r8 - thlphmp_zt(i,k,ixind) = 0._r8 + wpsclrp_sfc(i,sclr) = 0._r8 end do end do - end do + end if - do edsclr = 1, edsclr_dim - do i = 1, ncol - do k = 1, nzm_clubb - edsclrm_forcing(i,k,edsclr) = 0._r8 - edsclr_in(i,k,edsclr) = 0._r8 + if ( hydromet_dim > 0 ) then + !$acc parallel loop gang vector collapse(3) default(present) + do ixind=1, hydromet_dim + do k=1, nzm_clubb + do i=1, ncol + hydromet(i,k,ixind) = 0._r8 + wphydrometp(i,k,ixind) = 0._r8 + wp2hmp(i,k,ixind) = 0._r8 + rtphmp_zt(i,k,ixind) = 0._r8 + thlphmp_zt(i,k,ixind) = 0._r8 + end do end do end do - end do + end if - ! Define surface sources for transported variables for diffusion, will - ! be zero as these tendencies are done in vertical_diffusion - do edsclr = 1, edsclr_dim - do i = 1, ncol - wpedsclrp_sfc(i,edsclr) = 0._r8 + if ( edsclr_dim > 0 ) then + !$acc parallel loop gang vector collapse(3) default(present) + do edsclr = 1, edsclr_dim + do i = 1, ncol + do k = 1, nzm_clubb + edsclrm_forcing(i,k,edsclr) = 0._r8 + edsclr_in(i,k,edsclr) = 0._r8 + end do + end do end do - end do - ! need to initialize macmic coupling to zero - if (macmic_it==1) then - ttend_clubb_mc(:ncol,:) = 0._r8 - upwp_clubb_gw_mc(:ncol,:) = 0._r8 - vpwp_clubb_gw_mc(:ncol,:) = 0._r8 - thlp2_clubb_gw_mc(:ncol,:) = 0._r8 - wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + ! Define surface sources for transported variables for diffusion, will + ! be zero as these tendencies are done in vertical_diffusion + !$acc parallel loop gang vector collapse(2) default(present) + do edsclr = 1, edsclr_dim + do i = 1, ncol + wpedsclrp_sfc(i,edsclr) = 0._r8 + end do + end do end if @@ -3078,11 +3176,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do i = 1, ncol thlp2(i,k) = state1%q(i,k,ixthlp2) rtp2(i,k) = state1%q(i,k,ixrtp2) - rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - (rtpthlp_const*apply_const) - wpthlp(i,k) = state1%q(i,k,ixwpthlp) - (wpthlp_const*apply_const) - wprtp(i,k) = state1%q(i,k,ixwprtp) - (wprtp_const*apply_const) + rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - ( rtpthlp_const * apply_const ) + wpthlp(i,k) = state1%q(i,k,ixwpthlp) - ( wpthlp_const * apply_const ) + wprtp(i,k) = state1%q(i,k,ixwprtp) - ( wprtp_const * apply_const ) wp2(i,k) = state1%q(i,k,ixwp2) - wp3(i,k) = state1%q(i,k,ixwp3) - (wp3_const*apply_const) + wp3(i,k) = state1%q(i,k,ixwp3) - ( wp3_const * apply_const ) up2(i,k) = state1%q(i,k,ixup2) vp2(i,k) = state1%q(i,k,ixvp2) enddo @@ -3113,102 +3211,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - call t_startf('clubb_tend_cam:acc_copyin') - !$acc data copyin( sclr_idx, clubb_params, & - !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & - !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & - !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & - !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, clubb_params_single_col, & - !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & - !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & - !$acc vm_ref, ug, vg, grid_dx, grid_dy, & - !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & - !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & - !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & - !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & - !$acc rrho, prer_evap, inv_exner_clubb_surf, & - !$acc rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & - !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & - !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & - !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & - !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & - !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & - !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & - !$acc invrs_exner_zm, & - !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & - !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & - !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & - !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & - !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & - !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & - !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & - !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & - !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & - !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & - !$acc zi_g, zt_g, qrl_clubb, qrl, thv, dz_g, radf_clubb, & - !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & - !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & - !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & - !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & - !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & - !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & - !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & - !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & - !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) - - !$acc data if( sclr_dim > 0 ) & - !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & - !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) - - !$acc data if( edsclr_dim > 0 ) & - !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in, edsclr_out ) - - !$acc data if( hydromet_dim > 0 ) & - !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & - !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) - call t_stopf('clubb_tend_cam:acc_copyin') - - ! Define the CLUBB momentum grid (in height, units of m) !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb @@ -3225,7 +3227,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state - inv_exner_clubb(i,k) = 1._r8/((state1%pmid(i,k)/p0_clubb)**(rairv(i,k,lchnk)/cpairv(i,k,lchnk))) + inv_exner_clubb(i,k) = 1._r8 / ( ( state1%pmid(i,k) / p0_clubb )**( rairv(i,k,lchnk) / cpairv(i,k,lchnk) ) ) ! Compute virtual potential temperature, which is needed for CLUBB thv(i,k) = state1%t(i,k) * inv_exner_clubb(i,k) & @@ -3254,7 +3256,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute exner at the surface for converting the sensible heat fluxes ! to a flux of potential temperature for use as clubb's boundary conditions - inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) + inv_exner_clubb_surf(i) = 1._r8 / ( ( state1%pmid(i,pver) / p0_clubb )**( rairv(i,pver,lchnk) / cpairv(i,pver,lchnk) ) ) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. @@ -3286,7 +3288,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute mean w wind on thermo grid, convert from omega to w wm_zt(i,k+1) = -1._r8 * ( state1%omega(i,pver-k+1) - state1%omega(i,pver) ) & - / (rho_zt(i,k+1) * gravit) + / ( rho_zt(i,k+1) * gravit ) end do end do @@ -3947,14 +3949,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - do ixind=1,edsclr_dim - !$acc parallel loop gang vector collapse(2) default(present) - do k=1, nzm_clubb - do i=1, ncol - edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) + if ( edsclr_dim > 0 ) then + do ixind=1,edsclr_dim + !$acc parallel loop gang vector collapse(2) default(present) + do k=1, nzm_clubb + do i=1, ncol + edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) + end do end do end do - end do + end if if (do_clubb_mf) then do k=1, nzm_clubb @@ -4019,6 +4023,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') + + ! need to initialize macmic coupling to zero + if (macmic_it==1) then + ttend_clubb_mc(:ncol,:) = 0._r8 + upwp_clubb_gw_mc(:ncol,:) = 0._r8 + vpwp_clubb_gw_mc(:ncol,:) = 0._r8 + thlp2_clubb_gw_mc(:ncol,:) = 0._r8 + wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + end if + do k=1, pverp do i=1, ncol From 87af3301afd846312ad3a8ffe133486a1a88295f Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Wed, 16 Oct 2024 23:14:30 -0600 Subject: [PATCH 12/89] Adding/moving timing statements --- src/physics/cam/clubb_intr.F90 | 54 ++++++++++++++++------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index a12002e51b..bf0826f007 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2595,6 +2595,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & #endif + call t_startf('clubb_tend_cam') + do i = 1, pcols det_s(i) = 0.0_r8 det_ice(i) = 0.0_r8 @@ -2936,7 +2938,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:acc_copyin') - call t_startf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pverp @@ -3067,7 +3069,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if - ! Initialize EDMF outputs if (do_clubb_mf) then do k = 1, pverp @@ -3098,8 +3099,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do end if - - call t_stopf('clubb_tend_cam:NAR') if (clubb_do_icesuper) then @@ -3162,8 +3161,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'NITENDICE', initend, pcols, lchnk ) endif - call t_startf('clubb_tend_cam:NAR') - if (clubb_do_adv) then @@ -3210,7 +3207,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - ! Define the CLUBB momentum grid (in height, units of m) !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb @@ -3321,7 +3317,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! ------------------------------------------------- ! ! Begin case specific code for SCAM cases. ! ! This section of code block is NOT called in ! @@ -3381,6 +3376,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! operators (such as zt2zm_api, etc.) until AFTER the ! call to setup_grid_heights_api. + call t_stopf('clubb_tend_cam:ACCR') + call t_startf('clubb_tend_cam:NAR') !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) @@ -3393,15 +3390,21 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & clubb_config_flags%l_prescribed_avg_deltaz, & ! intent(in) lmin, nu_vert_res_dep, err_code ) ! intent(out) + if ( err_code == clubb_fatal_error ) then + call endrun(subr//': Fatal error in CLUBB setup_parameters') + end if + + call t_stopf('clubb_tend_cam:NAR') + + call t_startf('clubb_tend_cam:acc_copyin') !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & !$acc gr%weights_zt2zm, gr%weights_zm2zt, & !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & !$acc nu_vert_res_dep%nu6) + call t_stopf('clubb_tend_cam:acc_copyin') - if ( err_code == clubb_fatal_error ) then - call endrun(subr//': Fatal error in CLUBB setup_parameters') - end if + call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb @@ -3454,6 +3457,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Other Surface fluxes provided by host model if( (cld_macmic_num_steps > 1) .and. clubb_l_intr_sfc_flux_smooth ) then + call t_stopf('clubb_tend_cam:ACCR') + call t_startf('clubb_tend_cam:NAR') !$acc update host( state1%u, state1%v, state1%t, state1%pmid, cam_in%wsx, cam_in%wsy, rrho ) ! Adjust surface stresses using winds from the prior macmic iteration @@ -3469,6 +3474,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do !$acc update device( upwp_sfc, vpwp_sfc ) + call t_stopf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:ACCR') else @@ -3479,9 +3486,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - call t_stopf('clubb_tend_cam:NAR') - - + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core @@ -3561,6 +3566,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_inout(i,1) = rcm_inout(i,2) end do + call t_stopf('clubb_tend_cam:flip-index') + ! pressure,exner on momentum grid needed for mass flux calc. if (do_clubb_mf) then @@ -3589,7 +3596,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if - if (clubb_do_adv) then if (macmic_it == 1) then @@ -3637,7 +3643,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end do - if (clubb_l_do_expldiff_rtm_thlm) then !$acc parallel loop gang vector collapse(2) default(present) @@ -3656,8 +3661,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - call t_stopf('clubb_tend_cam:flip-index') - do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3851,7 +3854,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if enddo ! end time loop - call t_startf('clubb_tend_cam:NAR') if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -3877,14 +3879,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if - call t_stopf('clubb_tend_cam:NAR') ! Convert RTP2 and THLP2 to thermo grid for output - call t_startf('clubb_tend_cam:NAR') rtp2_zt = zm2zt_api( nzm_clubb, ncol, gr, rtp2_in ) thl2_zt = zm2zt_api( nzm_clubb, ncol, gr, thlp2_in ) wp2_zt = zm2zt_api( nzm_clubb, ncol, gr, wp2_in ) - call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') @@ -4011,7 +4010,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do call t_stopf('clubb_tend_cam:flip-index') - + call t_stopf('clubb_tend_cam:ACCR') call t_startf('clubb_tend_cam:acc_copyout') !$acc end data @@ -4021,7 +4020,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc end data call t_stopf('clubb_tend_cam:acc_copyout') - call t_startf('clubb_tend_cam:NAR') ! need to initialize macmic coupling to zero @@ -4338,7 +4336,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! then advances it's predictive equations second, this can lead to ! RHliq > 1 directly before microphysics is called. Therefore, we use ! ice_macro_tend to enforce RHliq <= 1 everywhere before microphysics is called. - call t_stopf('clubb_tend_cam:NAR') if (clubb_do_liqsupersat) then @@ -4396,7 +4393,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'FQTENDICE', fqtend, pcols, lchnk ) call t_stopf('clubb_cam_tend:do_liqsupersat') end if - call t_startf('clubb_tend_cam:NAR') ! ------------------------------------------------------------ ! ! The rest of the code deals with diagnosing variables ! @@ -4827,10 +4823,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif call t_stopf('clubb_tend_cam:NAR') - +#endif + + call t_stopf('clubb_tend_cam') return -#endif + end subroutine clubb_tend_cam subroutine clubb_emissions_cam (state, cam_in, ptend) From c85778ed06afcbe59f39568c7c3e416d9a3a1212 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Fri, 18 Oct 2024 13:41:14 -0600 Subject: [PATCH 13/89] Small cleanup and a little more GPUization. Passes ECT CPU vs GPU test and BFB on CPUs. --- src/physics/cam/clubb_intr.F90 | 310 ++++++++++++++++++--------------- 1 file changed, 170 insertions(+), 140 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index bf0826f007..aedfa22fbd 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2362,10 +2362,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Variables below are needed to compute energy integrals for conservation ! NOTE: Arrays of size PCOLS (all possible columns) can be used to access State, PBuf and History Subroutines - real(r8) :: ke_a(pcols), ke_b(pcols), te_a(pcols), te_b(pcols) - real(r8) :: wv_a(pcols), wv_b(pcols), wl_b(pcols), wl_a(pcols) - real(r8) :: se_dis(pcols), se_a(pcols), se_b(pcols), clubb_s(pcols,pver) - real(r8) :: eleak(pcols) + real(r8) :: te_a, se_a, ke_a, wv_a, wl_a + real(r8) :: te_b, se_b, ke_b, wv_b, wl_b + real(r8) :: se_dis(pcols), clubb_s(pcols,pver), eleak(pcols) real(r8) :: inv_exner_clubb(pcols,pverp) ! Inverse exner function consistent with CLUBB [-] real(r8) :: inv_exner_clubb_surf(pcols) ! Inverse exner function at the surface @@ -2572,6 +2571,22 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: temp2d(pcols,pver), temp2dp(pcols,pverp) ! temporary array for holding scaled outputs + real(r8), dimension(pcols,pver) :: & + rvmtend_clubb, & + rcmtend_clubb, & + rimtend_clubb, & + stend_clubb, & + utend_clubb, & + vtend_clubb, & + dpdlfliq, & + dpdlfice, & + dpdlft, & + detnliquid + + real(r8), dimension(pcols,pverp) :: & + wprcp_clubb, & + wpthvp_clubb + intrinsic :: max character(len=*), parameter :: subr='clubb_tend_cam' @@ -2619,6 +2634,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! + call t_startf('clubb_tend_cam:NAR') + ! Get indicees for cloud and ice mass and cloud and ice number call cnst_get_ind('Q',ixq) call cnst_get_ind('CLDLIQ',ixcldliq) @@ -2745,17 +2762,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! variable mesh grids and lat-lon grids call grid_size(state1, grid_dx, grid_dy) - - - ! Determine number of columns and which chunk computation is to be performed on + ! Determine number of columns and which chunk computation is to be performed on ncol = state%ncol lchnk = state%lchnk + ! Determine number of vertical levels used in clubb, thermo variables are nzt_clubb + ! and momentum variables are nzm_clubb nzt_clubb = pver + 1 - top_lev nzm_clubb = pverp + 1 - top_lev - - ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then call init_pdf_params_api( nzm_clubb, ncol, pdf_params_chnk(lchnk) ) @@ -2767,7 +2782,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & pdf_implicit_coefs_terms_chnk(lchnk) ) end if - !--------------------- Scalar Setting -------------------- dl_rad = clubb_detliq_rad @@ -2831,34 +2845,34 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected endif - ! Initialize the apply_const variable (note special logic is due to eularian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then apply_const = 0._r8 ! On first time through do not remove constant ! from moments since it has not been added yet endif - !--------------------- Initializations -------------------- - ! Set the ztodt timestep in pbuf for SILHS ztodtptr(:) = 1.0_r8*hdtime - + call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:acc_copyin') !$acc data copyin( sclr_idx, clubb_params_single_col, grid_dx, grid_dy, rairv, cpairv, radf_clubb, qrl, & !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & - !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & - !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & + !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, state1%s, state1%pint, & + !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, state1%phis, & !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & !$acc cloud_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc ttend_clubb_mc, upwp_clubb_gw_mc, vpwp_clubb_gw_mc, thlp2_clubb_gw_mc, wpthlp_clubb_gw_mc, & + !$acc ttend_clubb, upwp_clubb_gw, vpwp_clubb_gw, thlp2_clubb_gw, wpthlp_clubb_gw, & !$acc wp2up2, wp2vp2, ice_supersat_frac ) & !$acc copyout( temp2d, temp2dp, rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wm_zt_out, inv_exner_clubb, & - !$acc rcm, wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, thv, dz_g ) & + !$acc rcm, wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, thv, dz_g, & + !$acc clubbtop, se_dis, eleak, clubb_s, wpthvp_clubb, wprcp_clubb ) & !$acc create( upwp_sfc_pert, vpwp_sfc_pert, khzt_out, khzm_out, & !$acc fcor, um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & @@ -2936,8 +2950,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc create( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt ) & !$acc copyin( hm_metadata, hm_metadata%l_mix_rat_hm ) call t_stopf('clubb_tend_cam:acc_copyin') - - call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) @@ -2952,7 +2964,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pver do i = 1, pcols @@ -2960,7 +2971,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol @@ -2985,7 +2995,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & upwp_pert_inout(i,k) = 0.0_r8 vpwp_pert_inout(i,k) = 0.0_r8 - ! Initialize these to prevent crashing behavior wprcp_out(i,k) = 0._r8 rcm_in_layer_out(i,k) = 0._r8 @@ -2993,7 +3002,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & khzm_out(i,k) = 0._r8 khzt_out(i,k) = 0._r8 end do - end do + end do !$acc parallel loop gang vector default(present) do i = 1, ncol @@ -3069,6 +3078,20 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if + ! need to initialize macmic coupling to zero + if ( macmic_it == 1 ) then + !$acc parallel loop gang vector collapse(2) default(present) + do i = 1, ncol + do k = 1, pverp + ttend_clubb_mc(i,k) = 0._r8 + upwp_clubb_gw_mc(i,k) = 0._r8 + vpwp_clubb_gw_mc(i,k) = 0._r8 + thlp2_clubb_gw_mc(i,k) = 0._r8 + wpthlp_clubb_gw_mc(i,k) = 0._r8 + end do + end do + end if + ! Initialize EDMF outputs if (do_clubb_mf) then do k = 1, pverp @@ -3379,7 +3402,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:ACCR') call t_startf('clubb_tend_cam:NAR') !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) - + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) @@ -3395,7 +3418,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if call t_stopf('clubb_tend_cam:NAR') - call t_startf('clubb_tend_cam:acc_copyin') !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & !$acc gr%weights_zt2zm, gr%weights_zm2zt, & @@ -3403,7 +3425,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & !$acc nu_vert_res_dep%nu6) call t_stopf('clubb_tend_cam:acc_copyin') - call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) @@ -3436,16 +3457,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - - ! Compute some inputs from the thermodynamic grid - ! to the momentum grid + ! Compute some inputs from the thermodynamic grid to the momentum grid rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_ds_zt ) rho_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_zt ) invrs_rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, invrs_rho_ds_zt ) thv_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, thv_ds_zt ) wm_zm = zt2zm_api( nzm_clubb, ncol, gr, wm_zt ) - ! Surface fluxes provided by host model + ! Surface fluxes provided by host model !$acc parallel loop gang vector default(present) do i=1,ncol wpthlp_sfc(i) = cam_in%shf(i)/(cpairv(i,pver,lchnk)*rho_ds_zm(i,1)) ! Sensible heat flux @@ -3566,8 +3585,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_inout(i,1) = rcm_inout(i,2) end do - call t_stopf('clubb_tend_cam:flip-index') - ! pressure,exner on momentum grid needed for mass flux calc. if (do_clubb_mf) then @@ -3661,6 +3678,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif + call t_stopf('clubb_tend_cam:flip-index') + do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3821,7 +3840,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if - if (do_cldcool) then call t_startf('clubb_tend_cam:do_cldcool') @@ -3949,8 +3967,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do if ( edsclr_dim > 0 ) then + !$acc parallel loop gang vector collapse(3) default(present) do ixind=1,edsclr_dim - !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) @@ -4010,27 +4028,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do call t_stopf('clubb_tend_cam:flip-index') - call t_stopf('clubb_tend_cam:ACCR') - - call t_startf('clubb_tend_cam:acc_copyout') - !$acc end data - !$acc end data - !$acc end data - !$acc end data - !$acc end data - call t_stopf('clubb_tend_cam:acc_copyout') - - call t_startf('clubb_tend_cam:NAR') - - ! need to initialize macmic coupling to zero - if (macmic_it==1) then - ttend_clubb_mc(:ncol,:) = 0._r8 - upwp_clubb_gw_mc(:ncol,:) = 0._r8 - vpwp_clubb_gw_mc(:ncol,:) = 0._r8 - thlp2_clubb_gw_mc(:ncol,:) = 0._r8 - wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 - end if + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pverp do i=1, ncol @@ -4054,6 +4053,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Values to use above top_lev, for variables that have not already been ! set up there. These are mostly fill values that should not actually be ! used in the run, but may end up in diagnostic output. + !$acc parallel loop gang vector collapse(2) default(present) do k=1, top_lev-1 do i=1, ncol upwp(i,k) = 0._r8 @@ -4071,6 +4071,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Fill up arrays needed for McICA. Note we do not want the ghost point, ! thus why the second loop is needed. + !$acc parallel loop gang vector default(present) do i=1, pcols zi_out(i,1) = 0._r8 end do @@ -4081,6 +4082,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (lq(ixind)) then icnt=icnt+1 + !$acc parallel loop gang vector collapse(2) default(present) do k=1, top_lev-1 do i=1, ncol edsclr_out(i,k,icnt) = state1%q(i,k,ixind) @@ -4091,6 +4093,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do ! Compute static energy using CLUBB's variables + !$acc parallel loop gang vector collapse(2) default(present) do k=1,pver do i=1, ncol clubb_s(i,k) = cpairv(i,k,lchnk) * thlm(i,k) / inv_exner_clubb(i,k) & @@ -4104,66 +4107,59 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Initialize clubbtop to top_lev, for finding the highlest level CLUBB is ! active for informing where to apply the energy fixer. + !$acc parallel loop gang vector default(present) do i=1, ncol clubbtop(i) = top_lev do while ((rtp2(i,clubbtop(i)) <= 1.e-15_r8 .and. rcm(i,clubbtop(i)) == 0._r8) .and. clubbtop(i) < pver) - clubbtop(i) = clubbtop(i) + 1 + clubbtop(i) = clubbtop(i) + 1 end do end do - ! - ! set pbuf field so that HB scheme is only applied above CLUBB top - ! - if (do_hb_above_clubb) then - call pbuf_set_field(pbuf, clubbtop_idx, clubbtop) - endif + !$acc parallel loop gang vector default(present) do i=1, ncol - se_a(i) = 0._r8 - ke_a(i) = 0._r8 - wv_a(i) = 0._r8 - wl_a(i) = 0._r8 - - se_b(i) = 0._r8 - ke_b(i) = 0._r8 - wv_b(i) = 0._r8 - wl_b(i) = 0._r8 - end do - ! NO COLLAPSE(2) - do i=1, ncol + se_a = 0._r8 + ke_a = 0._r8 + wv_a = 0._r8 + wl_a = 0._r8 + + se_b = 0._r8 + ke_b = 0._r8 + wv_b = 0._r8 + wl_b = 0._r8 + do k=1,pver ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water ! after CLUBB is called. This is for energy conservation purposes. - se_a(i) = se_a(i) + clubb_s(i,k)*state1%pdel(i,k)*rga - ke_a(i) = ke_a(i) + 0.5_r8*(um(i,k)**2+vm(i,k)**2)*state1%pdel(i,k)*rga - wv_a(i) = wv_a(i) + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga - wl_a(i) = wl_a(i) + (rcm(i,k))*state1%pdeldry(i,k)*rga + se_a = se_a + clubb_s(i,k)*state1%pdel(i,k)*rga + ke_a = ke_a + 0.5_r8*(um(i,k)**2+vm(i,k)**2)*state1%pdel(i,k)*rga + wv_a = wv_a + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga + wl_a = wl_a + (rcm(i,k))*state1%pdeldry(i,k)*rga end do - end do - ! NO COLLAPSE(2) - do i=1, ncol + ! Based on these integrals, compute the total energy after CLUBB call + te_a = se_a + ke_a + (latvap+latice) * wv_a + latice * wl_a + do k=1, pver ! Do the same as above, but for before CLUBB was called. - se_b(i) = se_b(i) + state1%s(i,k)*state1%pdel(i,k)*rga - ke_b(i) = ke_b(i) + 0.5_r8*(state1%u(i,k)**2+state1%v(i,k)**2)*state1%pdel(i,k)*rga - wv_b(i) = wv_b(i) + state1%q(i,k,ixq)*state1%pdeldry(i,k)*rga - wl_b(i) = wl_b(i) + state1%q(i,k,ixcldliq)*state1%pdeldry(i,k)*rga + se_b = se_b + state1%s(i,k)*state1%pdel(i,k)*rga + ke_b = ke_b + 0.5_r8*(state1%u(i,k)**2+state1%v(i,k)**2)*state1%pdel(i,k)*rga + wv_b = wv_b + state1%q(i,k,ixq)*state1%pdeldry(i,k)*rga + wl_b = wl_b + state1%q(i,k,ixcldliq)*state1%pdeldry(i,k)*rga end do - end do - - do i=1, ncol - ! Based on these integrals, compute the total energy before and after CLUBB call - te_a(i) = se_a(i) + ke_a(i) + (latvap+latice) * wv_a(i) + latice * wl_a(i) - te_b(i) = se_b(i) + ke_b(i) + (latvap+latice) * wv_b(i) + latice * wl_b(i) + ! Based on these integrals, compute the total energy before CLUBB call + te_b = se_b + ke_b + (latvap+latice) * wv_b + latice * wl_b ! Take into account the surface fluxes of heat and moisture ! Use correct qflux from cam_in, not lhf/latvap as was done previously - te_b(i) = te_b(i) + (cam_in%shf(i)+cam_in%cflx(i,1)*(latvap+latice)) * hdtime + te_b = te_b + (cam_in%shf(i)+cam_in%cflx(i,1)*(latvap+latice)) * hdtime ! Compute the disbalance of total energy, over depth where CLUBB is active - se_dis(i) = (te_a(i) - te_b(i))/(state1%pint(i,pverp)-state1%pint(i,clubbtop(i))) + se_dis(i) = ( te_a - te_b ) / ( state1%pint(i,pverp) - state1%pint(i,clubbtop(i)) ) + + eleak(i) = ( te_a - te_b ) / hdtime + end do ! Fix the total energy coming out of CLUBB so it achieves energy conservation. @@ -4174,14 +4170,39 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! when using specified dynamics, so allow this to be turned off via a namelist ! variable. if (clubb_do_energyfix) then + + !$acc parallel loop gang vector default(present) do i=1, ncol + do k=clubbtop(i),pver clubb_s(i,k) = clubb_s(i,k) - se_dis(i)*gravit end do ! convert to units of +ve [K] se_dis(i) = -1._r8*se_dis(i)*gravit/cpairv(i,pver,lchnk) + end do + endif + + !$acc parallel loop gang vector collapse(2) default(present) + do k=1, pverp + do i=1, ncol + wpthvp_clubb(i,k) = wpthvp(i,k) * cpair + wprcp_clubb(i,k) = wprcp(i,k) * latvap + end do + end do + + call t_stopf('clubb_tend_cam:ACCR') + + call t_startf('clubb_tend_cam:acc_copyout') + !$acc end data + !$acc end data + !$acc end data + !$acc end data + !$acc end data + call t_stopf('clubb_tend_cam:acc_copyout') + + call t_startf('clubb_tend_cam:NAR') call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) @@ -4299,36 +4320,27 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if end do + + rvmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + rcmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + rimtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + stend_clubb(:ncol,:pver) = ptend_loc%s(:ncol,:pver) + utend_clubb(:ncol,:pver) = ptend_loc%u(:ncol,:pver) + vtend_clubb(:ncol,:pver) = ptend_loc%v(:ncol,:pver) + cmeliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - - call outfld('KVH_CLUBB', khzm, pcols, lchnk) - - eleak(:ncol) = (te_a(:ncol) - te_b(:ncol))/hdtime - call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) - call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) + ! + ! set pbuf field so that HB scheme is only applied above CLUBB top + ! + if (do_hb_above_clubb) then + call pbuf_set_field(pbuf, clubbtop_idx, clubbtop) + endif ! ------------------------------------------------- ! ! End column computation of CLUBB, begin to apply ! ! and compute output, etc ! ! ------------------------------------------------- ! - ! Output CLUBB tendencies (convert dry basis to wet for consistency with history variable definition) - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'RVMTEND_CLUBB', temp2d, pcols, lchnk) - - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'RCMTEND_CLUBB', temp2d, pcols, lchnk) - - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'RIMTEND_CLUBB', temp2d, pcols, lchnk) - - call outfld( 'STEND_CLUBB', ptend_loc%s,pcols, lchnk) - call outfld( 'UTEND_CLUBB', ptend_loc%u,pcols, lchnk) - call outfld( 'VTEND_CLUBB', ptend_loc%v,pcols, lchnk) - - cmeliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'CMELIQ', cmeliq, pcols, lchnk) - call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) @@ -4419,6 +4431,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do k=1,pver do i=1,ncol + if( state1%t(i,k) > meltpt_temp ) then dum1 = 0.0_r8 elseif ( state1%t(i,k) < dt_low ) then @@ -4455,19 +4468,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water - - ! output moist basis to be consistent with history variable definition - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) - - ! output moist basis to be consistent with history variable definition - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'DPDLFICE', temp2d, pcols, lchnk) - - temp2d(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) - call outfld( 'DPDLFT', temp2d, pcols, lchnk) - - call outfld( 'DETNLIQTND', ptend_loc%q(:,:,ixnumliq),pcols, lchnk ) + dpdlfliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + dpdlfice(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + dpdlft(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) + detnliquid(:ncol,:pver) = ptend_loc%q(:,:,ixnumliq) call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) @@ -4494,11 +4498,20 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & relvarmax = 10.0_r8 endif - relvar(:,:) = relvarmax ! default + do i = 1, ncol + do k = 1, pver + relvar(i,k) = relvarmax ! default + end do + end do if (deep_scheme .ne. 'CLUBB_SGS') then - where (rcm(:ncol,:pver) /= 0 .and. qclvar(:ncol,:pver) /= 0) & - relvar(:ncol,:pver) = min(relvarmax,max(0.001_r8,rcm(:ncol,:pver)**2/qclvar(:ncol,:pver))) + do i = 1, ncol + do k = 1, pver + if ( rcm(i,k) /= 0 .and. qclvar(i,k) /= 0 ) then + relvar(i,k) = min( relvarmax, max(0.001_r8, rcm(i,k)**2 / qclvar(i,k) ) ) + end if + end do + end do endif ! ------------------------------------------------- ! @@ -4705,8 +4718,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ustar2, obklen, kbfs, pblh, dummy2, & state1%zi, cloud_frac(:,1:pver), 1._r8-cam_in%landfrac, dummy3) - ! Output the PBL depth - call outfld('PBLH', pblh, pcols, lchnk) ! Assign the first pver levels of cloud_frac back to cld cld(:,1:pver) = cloud_frac(:,1:pver) @@ -4715,6 +4726,30 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! END CLOUD FRACTION DIAGNOSIS, begin to store variables back into buffer ! ! --------------------------------------------------------------------------------- ! + call outfld( 'DETNLIQTND', detnliquid,pcols, lchnk ) + + ! Output CLUBB tendencies (convert dry basis to wet for consistency with history variable definition) + call outfld( 'RVMTEND_CLUBB', rvmtend_clubb, pcols, lchnk) + call outfld( 'RCMTEND_CLUBB', rcmtend_clubb, pcols, lchnk) + call outfld( 'RIMTEND_CLUBB', rimtend_clubb, pcols, lchnk) + call outfld( 'STEND_CLUBB', stend_clubb, pcols, lchnk) + call outfld( 'UTEND_CLUBB', utend_clubb, pcols, lchnk) + call outfld( 'VTEND_CLUBB', vtend_clubb, pcols, lchnk) + + call outfld( 'CMELIQ', cmeliq, pcols, lchnk) + + ! output moist basis to be consistent with history variable definition + call outfld( 'DPDLFLIQ', dpdlfliq, pcols, lchnk) + call outfld( 'DPDLFICE', dpdlfice, pcols, lchnk) + call outfld( 'DPDLFT', dpdlft, pcols, lchnk) + + ! Output the PBL depth + call outfld('PBLH', pblh, pcols, lchnk) + + call outfld('KVH_CLUBB', khzm, pcols, lchnk) + call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) + call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) + ! Output calls of variables goes here call outfld( 'RELVAR', relvar, pcols, lchnk ) call outfld( 'RHO_CLUBB', rho(:,1:pver), pcols, lchnk ) @@ -4731,13 +4766,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'RCM_CLUBB', rcm(:,1:pver), pcols, lchnk ) call outfld( 'RTM_CLUBB', rtm(:,1:pver), pcols, lchnk ) call outfld( 'THLM_CLUBB', thlm(:,1:pver), pcols, lchnk ) - - temp2dp(:ncol,:) = wprcp(:ncol,:) * latvap - call outfld( 'WPRCP_CLUBB', temp2dp, pcols, lchnk ) - - temp2dp(:ncol,:) = wpthvp(:ncol,:) * cpair - call outfld( 'WPTHVP_CLUBB', temp2dp, pcols, lchnk ) - + call outfld( 'WPRCP_CLUBB', wprcp_clubb, pcols, lchnk ) + call outfld( 'WPTHVP_CLUBB', wpthvp_clubb, pcols, lchnk ) call outfld( 'RTP2_ZT_CLUBB', rtp2_zt_out(:,1:pver), pcols, lchnk ) call outfld( 'THLP2_ZT_CLUBB', thl2_zt_out(:,1:pver), pcols, lchnk ) call outfld( 'WP2_ZT_CLUBB', wp2_zt_out(:,1:pver), pcols, lchnk ) From 2772bb4aa280d4c4dc4d5253fa2fc672dde09b48 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 9 Sep 2024 20:04:06 -0400 Subject: [PATCH 14/89] Port check_energy_chng, check_energy_timestep_init to CCPP-ized subroutines --- bld/configure | 1 + src/dynamics/eul/dp_coupling.F90 | 4 +- src/dynamics/fv/dp_coupling.F90 | 4 +- src/dynamics/mpas/dp_coupling.F90 | 4 +- src/dynamics/se/dp_coupling.F90 | 4 +- src/physics/cam/check_energy.F90 | 302 +-------------------------- src/physics/cam/check_energy_cam.F90 | 211 +++++++++++++++++++ src/physics/cam/physpkg.F90 | 5 +- src/physics/cam/zm_conv_intr.F90 | 1 - src/physics/cam7/physpkg.F90 | 6 +- 10 files changed, 232 insertions(+), 310 deletions(-) create mode 100644 src/physics/cam/check_energy_cam.F90 diff --git a/bld/configure b/bld/configure index 86c6c4e65b..4b898b9d88 100755 --- a/bld/configure +++ b/bld/configure @@ -2340,6 +2340,7 @@ sub write_filepath print $fh "$camsrcdir/src/atmos_phys/schemes/tropopause_find\n"; print $fh "$camsrcdir/src/atmos_phys/schemes/zhang_mcfarlane\n"; print $fh "$camsrcdir/src/atmos_phys/schemes/dry_adiabatic_adjust\n"; + print $fh "$camsrcdir/src/atmos_phys/schemes/check_energy\n"; print $fh "$camsrcdir/src/atmos_phys/schemes/utilities\n"; # Dynamics package and test utilities diff --git a/src/dynamics/eul/dp_coupling.F90 b/src/dynamics/eul/dp_coupling.F90 index bc900e2d0e..8e3eb64a21 100644 --- a/src/dynamics/eul/dp_coupling.F90 +++ b/src/dynamics/eul/dp_coupling.F90 @@ -14,7 +14,7 @@ module dp_coupling use physconst, only: cpair, gravit, rair, zvir use air_composition, only: rairv use geopotential, only: geopotential_t - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init #if (defined SPMD) use spmd_dyn, only: buf1, buf1win, buf2, buf2win, & spmdbuf_siz, local_dp_map, & @@ -291,7 +291,7 @@ subroutine d_p_coupling(ps, t3, u3, v3, q3, & ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) end do diff --git a/src/dynamics/fv/dp_coupling.F90 b/src/dynamics/fv/dp_coupling.F90 index fc02821471..af2d13b12e 100644 --- a/src/dynamics/fv/dp_coupling.F90 +++ b/src/dynamics/fv/dp_coupling.F90 @@ -12,7 +12,7 @@ module dp_coupling use physconst, only: gravit, zvir use air_composition, only: cpairv, rairv use geopotential, only: geopotential_t - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init use dynamics_vars, only: T_FVDYCORE_GRID, t_fvdycore_state use dyn_internal_state,only: get_dyn_state use dyn_comp, only: dyn_import_t, dyn_export_t, fv_print_dpcoup_warn @@ -621,7 +621,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do call t_stopf('derived_fields') diff --git a/src/dynamics/mpas/dp_coupling.F90 b/src/dynamics/mpas/dp_coupling.F90 index 10d75b4b8c..c312f1e2f9 100644 --- a/src/dynamics/mpas/dp_coupling.F90 +++ b/src/dynamics/mpas/dp_coupling.F90 @@ -413,7 +413,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! MPAS prognostic fields. use geopotential, only: geopotential_t - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init use shr_vmath_mod, only: shr_vmath_log use phys_control, only: waccmx_is use cam_thermo, only: cam_thermo_dry_air_update, cam_thermo_water_update @@ -564,7 +564,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do diff --git a/src/dynamics/se/dp_coupling.F90 b/src/dynamics/se/dp_coupling.F90 index 919b7f3510..9de31132a2 100644 --- a/src/dynamics/se/dp_coupling.F90 +++ b/src/dynamics/se/dp_coupling.F90 @@ -546,7 +546,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) use phys_control, only: waccmx_is use geopotential, only: geopotential_t use static_energy, only: update_dry_static_energy_run - use check_energy, only: check_energy_timestep_init + use check_energy_cam,only: check_energy_cam_timestep_init use hycoef, only: hyai, ps0 use shr_vmath_mod, only: shr_vmath_log use qneg_module, only: qneg3 @@ -707,7 +707,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) cpairv(1:ncol,:,lchnk), errflg, errmsg) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do ! lchnk diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9c569387e0..5e1df3a967 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -26,10 +26,9 @@ module check_energy use gmean_mod, only: gmean use physconst, only: gravit, rga, latvap, latice, cpair, rair - use air_composition, only: cpairv, rairv, cp_or_cv_dycore + use air_composition, only: cpairv, cp_or_cv_dycore use physics_types, only: physics_state, physics_tend, physics_ptend, physics_ptend_init use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind - use time_manager, only: is_first_step use cam_logfile, only: iulog use scamMod, only: single_column, use_camiop, heat_glob_scm use cam_history, only: outfld, write_camiop @@ -45,8 +44,6 @@ module check_energy public :: check_energy_register ! register fields in physics buffer public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean public :: check_energy_init ! initialization of module - public :: check_energy_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes - public :: check_energy_chng ! check changes in integrals against cumulative boundary fluxes public :: check_energy_gmean ! global means of physics input and output total energy public :: check_energy_fix ! add global mean energy difference as a heating public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes @@ -67,11 +64,11 @@ module check_energy ! Physics buffer indices - integer :: teout_idx = 0 ! teout index in physics buffer - integer :: dtcore_idx = 0 ! dtcore index in physics buffer - integer :: dqcore_idx = 0 ! dqcore index in physics buffer - integer :: ducore_idx = 0 ! ducore index in physics buffer - integer :: dvcore_idx = 0 ! dvcore index in physics buffer + integer, public :: teout_idx = 0 ! teout index in physics buffer + integer, public :: dtcore_idx = 0 ! dtcore index in physics buffer + integer, public :: dqcore_idx = 0 ! dqcore index in physics buffer + integer, public :: ducore_idx = 0 ! ducore index in physics buffer + integer, public :: dvcore_idx = 0 ! dvcore index in physics buffer type check_tracers_data real(r8) :: tracer(pcols,pcnst) ! initial vertically integrated total (kinetic + static) energy @@ -219,293 +216,6 @@ end subroutine check_energy_init !=============================================================================== - subroutine check_energy_timestep_init(state, tend, pbuf, col_type) - use cam_thermo, only: get_hydrostatic_energy - use physics_buffer, only: physics_buffer_desc, pbuf_set_field - use cam_abortutils, only: endrun - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use physics_types, only: phys_te_idx, dyn_te_idx -!----------------------------------------------------------------------- -! Compute initial values of energy and water integrals, -! zero cumulative tendencies -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state), intent(inout) :: state - type(physics_tend ), intent(inout) :: tend - type(physics_buffer_desc), pointer :: pbuf(:) - integer, optional :: col_type ! Flag inidicating whether using grid or subcolumns -!---------------------------Local storage------------------------------- - real(r8) :: cp_or_cv(state%psetcols,pver) - integer lchnk ! chunk identifier - integer ncol ! number of atmospheric columns -!----------------------------------------------------------------------- - - lchnk = state%lchnk - ncol = state%ncol - - ! cp_or_cv needs to be allocated to a size which matches state and ptend - ! If psetcols == pcols, cpairv is the correct size and just copy into cp_or_cv - ! If psetcols > pcols and all cpairv match cpair, then assign the constant cpair - - if (state%psetcols == pcols) then - cp_or_cv(:,:) = cpairv(:,:,lchnk) - else if (state%psetcols > pcols .and. all(cpairv(:,:,lchnk) == cpair)) then - cp_or_cv(1:ncol,:) = cpair - else - call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') - end if - ! - ! CAM physics total energy - ! - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_physics, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol),& - te = state%te_ini(1:ncol,phys_te_idx), H2O = state%tw_ini(1:ncol)) - ! - ! Dynamical core total energy - ! - state%temp_ini(:ncol,:) = state%T(:ncol,:) - state%z_ini(:ncol,:) = state%zm(:ncol,:) - if (vc_dycore == vc_height) then - ! - ! MPAS specific hydrostatic energy computation (internal energy) - ! - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair-rair - endif - - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - z_mid = state%z_ini(1:ncol,:), & - te = state%te_ini(1:ncol,dyn_te_idx), H2O = state%tw_ini(1:ncol)) - else if (vc_dycore == vc_dry_pressure) then - ! - ! SE specific hydrostatic energy (enthalpy) - ! - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair - endif - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_dry_pressure, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - te = state%te_ini(1:ncol,dyn_te_idx), H2O = state%tw_ini(1:ncol)) - else - ! - ! dycore energy is the same as physics - ! - state%te_ini(1:ncol,dyn_te_idx) = state%te_ini(1:ncol,phys_te_idx) - end if - state%te_cur(:ncol,:) = state%te_ini(:ncol,:) - state%tw_cur(:ncol) = state%tw_ini(:ncol) - -! zero cummulative boundary fluxes - tend%te_tnd(:ncol) = 0._r8 - tend%tw_tnd(:ncol) = 0._r8 - - state%count = 0 - -! initialize physics buffer - if (is_first_step()) then - call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) - end if - - end subroutine check_energy_timestep_init - -!=============================================================================== - - subroutine check_energy_chng(state, tend, name, nstep, ztodt, & - flx_vap, flx_cnd, flx_ice, flx_sen) - use cam_thermo, only: get_hydrostatic_energy - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use cam_abortutils, only: endrun - use physics_types, only: phys_te_idx, dyn_te_idx -!----------------------------------------------------------------------- -! Check that the energy and water change matches the boundary fluxes -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state) , intent(inout) :: state - type(physics_tend ) , intent(inout) :: tend - character*(*),intent(in) :: name ! parameterization name for fluxes - integer , intent(in ) :: nstep ! current timestep number - real(r8), intent(in ) :: ztodt ! 2 delta t (model time increment) - real(r8), intent(in ) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) - real(r8), intent(in ) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) - real(r8), intent(in ) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) - real(r8), intent(in ) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) - -!******************** BAB ****************************************************** -!******* Note that the precip and ice fluxes are in precip units (m/s). ******** -!******* I would prefer to have kg/m2/s. ******** -!******* I would also prefer liquid (not total) and ice fluxes ******** -!******************************************************************************* - -!---------------------------Local storage------------------------------- - - real(r8) :: te_xpd(state%ncol) ! expected value (f0 + dt*boundary_flux) - real(r8) :: te_dif(state%ncol) ! energy of input state - original energy - real(r8) :: te_tnd(state%ncol) ! tendency from last process - real(r8) :: te_rer(state%ncol) ! relative error in energy column - - real(r8) :: tw_xpd(state%ncol) ! expected value (w0 + dt*boundary_flux) - real(r8) :: tw_dif(state%ncol) ! tw_inp - original water - real(r8) :: tw_tnd(state%ncol) ! tendency from last process - real(r8) :: tw_rer(state%ncol) ! relative error in water column - - real(r8) :: te(state%ncol) ! vertical integral of total energy - real(r8) :: tw(state%ncol) ! vertical integral of total water - real(r8) :: cp_or_cv(state%psetcols,pver) ! cp or cv depending on vcoord - real(r8) :: scaling(state%psetcols,pver) ! scaling for conversion of temperature increment - real(r8) :: temp(state%ncol,pver) ! temperature - - real(r8) :: se(state%ncol) ! enthalpy or internal energy (J/m2) - real(r8) :: po(state%ncol) ! surface potential or potential energy (J/m2) - real(r8) :: ke(state%ncol) ! kinetic energy (J/m2) - real(r8) :: wv(state%ncol) ! column integrated vapor (kg/m2) - real(r8) :: liq(state%ncol) ! column integrated liquid (kg/m2) - real(r8) :: ice(state%ncol) ! column integrated ice (kg/m2) - - integer lchnk ! chunk identifier - integer ncol ! number of atmospheric columns - integer i ! column index -!----------------------------------------------------------------------- - - lchnk = state%lchnk - ncol = state%ncol - - ! If psetcols == pcols, cpairv is the correct size and just copy into cp_or_cv - ! If psetcols > pcols and all cpairv match cpair, then assign the constant cpair - - if (state%psetcols == pcols) then - cp_or_cv(:,:) = cpairv(:,:,lchnk) - else if (state%psetcols > pcols .and. all(cpairv(:,:,:) == cpair)) then - cp_or_cv(:,:) = cpair - else - call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') - end if - - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_physics, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - te = te(1:ncol), H2O = tw(1:ncol), se=se(1:ncol),po=po(1:ncol), & - ke=ke(1:ncol),wv=wv(1:ncol),liq=liq(1:ncol),ice=ice(1:ncol)) - ! compute expected values and tendencies - do i = 1, ncol - ! change in static energy and total water - te_dif(i) = te(i) - state%te_cur(i,phys_te_idx) - tw_dif(i) = tw(i) - state%tw_cur(i) - - ! expected tendencies from boundary fluxes for last process - te_tnd(i) = flx_vap(i)*(latvap+latice) - (flx_cnd(i) - flx_ice(i))*1000._r8*latice + flx_sen(i) - tw_tnd(i) = flx_vap(i) - flx_cnd(i) *1000._r8 - - ! cummulative tendencies from boundary fluxes - tend%te_tnd(i) = tend%te_tnd(i) + te_tnd(i) - tend%tw_tnd(i) = tend%tw_tnd(i) + tw_tnd(i) - - ! expected new values from previous state plus boundary fluxes - te_xpd(i) = state%te_cur(i,phys_te_idx) + te_tnd(i)*ztodt - tw_xpd(i) = state%tw_cur(i) + tw_tnd(i)*ztodt - - ! relative error, expected value - input state / previous state - te_rer(i) = (te_xpd(i) - te(i)) / state%te_cur(i,phys_te_idx) - end do - - ! relative error for total water (allow for dry atmosphere) - tw_rer = 0._r8 - where (state%tw_cur(:ncol) > 0._r8) - tw_rer(:ncol) = (tw_xpd(:ncol) - tw(:ncol)) / state%tw_cur(:ncol) - end where - - ! error checking - if (print_energy_errors) then - if (any(abs(te_rer(1:ncol)) > 1.E-14_r8 .or. abs(tw_rer(1:ncol)) > 1.E-10_r8)) then - do i = 1, ncol - ! the relative error threshold for the water budget has been reduced to 1.e-10 - ! to avoid messages generated by QNEG3 calls - ! PJR- change to identify if error in energy or water - if (abs(te_rer(i)) > 1.E-14_r8 ) then - state%count = state%count + 1 - write(iulog,*) "significant energy conservation error after ", name, & - " count", state%count, " nstep", nstep, "chunk", lchnk, "col", i - write(iulog,*) te(i),te_xpd(i),te_dif(i),tend%te_tnd(i)*ztodt, & - te_tnd(i)*ztodt,te_rer(i) - endif - if ( abs(tw_rer(i)) > 1.E-10_r8) then - state%count = state%count + 1 - write(iulog,*) "significant water conservation error after ", name, & - " count", state%count, " nstep", nstep, "chunk", lchnk, "col", i - write(iulog,*) tw(i),tw_xpd(i),tw_dif(i),tend%tw_tnd(i)*ztodt, & - tw_tnd(i)*ztodt,tw_rer(i) - end if - end do - end if - end if - - ! copy new value to state - - do i = 1, ncol - state%te_cur(i,phys_te_idx) = te(i) - state%tw_cur(i) = tw(i) - end do - - ! - ! Dynamical core total energy - ! - if (vc_dycore == vc_height) then - ! - ! compute cv if vertical coordinate is height: cv = cp - R - ! - ! Note: cp_or_cv set above for pressure coordinate - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair-rair - endif - scaling(:,:) = cpairv(:,:,lchnk)/cp_or_cv(:,:) !cp/cv scaling - temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:)) - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), & - vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - z_mid = state%z_ini(1:ncol,:), & - te = state%te_cur(1:ncol,dyn_te_idx), H2O = state%tw_cur(1:ncol)) - else if (vc_dycore == vc_dry_pressure) then - ! - ! SE specific hydrostatic energy - ! - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - scaling(:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair - scaling(:ncol,:) = 1.0_r8 - endif - ! - ! enthalpy scaling for energy consistency - ! - temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:)) - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), & - vc_dry_pressure, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - te = state%te_cur(1:ncol,dyn_te_idx), H2O = state%tw_cur(1:ncol)) - else - state%te_cur(1:ncol,dyn_te_idx) = te(1:ncol) - end if - end subroutine check_energy_chng - - subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_get_chunk diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 new file mode 100644 index 0000000000..2bc48d5327 --- /dev/null +++ b/src/physics/cam/check_energy_cam.F90 @@ -0,0 +1,211 @@ +! Shim for CCPP-ized check_energy routines in CAM +module check_energy_cam + use shr_kind_mod, only: r8 => shr_kind_r8 + use ppgrid, only: pcols, pver + use constituents, only: pcnst + use physics_types, only: physics_state, physics_tend + + implicit none + private + + public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes + public :: check_energy_cam_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes + +contains + ! Compute initial values of energy and water integrals, + ! zero cumulative tendencies + subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) + use physics_buffer, only: physics_buffer_desc, pbuf_set_field + use cam_abortutils, only: endrun + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use physics_types, only: phys_te_idx, dyn_te_idx + use time_manager, only: is_first_step + use physconst, only: cpair, rair + use air_composition, only: cpairv, cp_or_cv_dycore + + ! To remove, pbuf indices in check_energy + use check_energy, only: teout_idx + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_timestep_init + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + type(physics_buffer_desc), pointer :: pbuf(:) + integer, optional :: col_type ! Flag indicating whether using grid or subcolumns + + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the + ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special + ! handling inside this shim module. (hplin, 9/9/24) + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + else if (state%psetcols > pcols) then + ! Subcolumns code + ! Subcolumns specific error handling + if(.not. all(cpairv(:,:,lchnk) == cpair)) then + call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(1:ncol,:) = cpair + + if (vc_dycore == vc_height) then + ! MPAS specific hydrostatic energy computation (internal energy) + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + else if(vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy (enthalpy) + local_cp_or_cv_dycore(:ncol,:) = cpair + else + ! cp_or_cv is not used in the underlying subroutine, zero it out to be sure + local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 + endif + end if + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_timestep_init( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & + te_ini_dyn = state%te_ini(1:ncol,dyn_te_idx), & + tw_ini = state%tw_ini(1:ncol), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + count = state%count, & + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + errmsg = errmsg, & + errflg = errflg & + ) + + ! initialize physics buffer + if (is_first_step()) then + call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) + end if + + end subroutine check_energy_cam_timestep_init + + ! Check that the energy and water change matches the boundary fluxes + subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & + flx_vap, flx_cnd, flx_ice, flx_sen) + use cam_thermo, only: get_hydrostatic_energy + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use cam_abortutils, only: endrun + use physics_types, only: phys_te_idx, dyn_te_idx + use physconst, only: cpair, rair + use air_composition, only: cpairv, cp_or_cv_dycore + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_run + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + character*(*),intent(in) :: name ! parameterization name for fluxes + integer , intent(in) :: nstep ! current timestep number + real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) + real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) + real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) + real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) + real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) + + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + integer :: i ! column index + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: scaling_dycore(state%ncol,pver) + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + + scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + elseif(state%psetcols > pcols) then + ! Subcolumns + if(.not. all(cpairv(:,:,:) == cpair)) then + call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(:,:) = cpair + + ! Note: cp_or_cv set above for pressure coordinate + if (vc_dycore == vc_height) then + ! compute cv if vertical coordinate is height: cv = cp - R + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + else if (vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy + local_cp_or_cv_dycore(:ncol,:) = cpair + scaling_dycore(:ncol,:) = 1.0_r8 + else + ! Moist pressure... use phys formula + local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:,lchnk) + scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + end if + endif + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_run( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + scaling_dycore = scaling_dycore(1:ncol,:), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + count = state%count, & + ztodt = ztodt, & + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + errmsg = errmsg, & + errflg = errflg & + ) + + end subroutine check_energy_cam_chng +end module check_energy_cam \ No newline at end of file diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index ba36670ce8..227274355e 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -2044,7 +2044,8 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend, convect_deep_tend_2, deep_scheme_does_scav_trans use time_manager, only: is_first_step, get_nstep use convect_shallow, only: convect_shallow_tend - use check_energy, only: check_energy_chng, check_energy_fix, check_energy_timestep_init + use check_energy_cam,only: check_energy_cam_timestep_init, check_energy_cam_chng + use check_energy, only: check_energy_fix use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2630,7 +2631,7 @@ subroutine tphysbc (ztodt, state, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 4113c33a4b..5db6d1bc03 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -393,7 +393,6 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & use time_manager, only: get_nstep, is_first_step use physics_buffer, only : pbuf_get_field, physics_buffer_desc, pbuf_old_tim_idx use constituents, only: pcnst, cnst_get_ind, cnst_is_convtran1 - use check_energy, only: check_energy_chng use physconst, only: gravit, latice, latvap, tmelt, cpwv, cpliq, rh2o use phys_control, only: cam_physpkg_is diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 83d03c46d1..ad5bc9913e 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1366,7 +1366,8 @@ subroutine tphysac (ztodt, cam_in, & use aoa_tracers, only: aoa_tracers_timestep_tend use physconst, only: rhoh2o use aero_model, only: aero_model_drydep - use check_energy, only: check_energy_chng, tot_energy_phys + use check_energy_cam, only: check_energy_cam_timestep_init, check_energy_cam_chng + use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun @@ -1405,7 +1406,6 @@ subroutine tphysac (ztodt, cam_in, & use aero_model, only: aero_model_wetdep use aero_wetdep_cam, only: wetdep_lq use physics_buffer, only: col_type_subcol - use check_energy, only: check_energy_timestep_init use carma_intr, only: carma_wetdep_tend, carma_timestep_tend, carma_emission_tend use carma_flags_mod, only: carma_do_aerosol, carma_do_emission, carma_do_detrain use carma_flags_mod, only: carma_do_cldice, carma_do_cldliq, carma_do_wetdep @@ -1775,7 +1775,7 @@ subroutine tphysac (ztodt, cam_in, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then From 50afaa6917eb7a40f4f344a8943be30a71c0240f Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 9 Sep 2024 23:56:53 -0400 Subject: [PATCH 15/89] Update physical constants to pass into subroutine --- src/physics/cam/check_energy_cam.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 2bc48d5327..4f686b598d 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -118,7 +118,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure use cam_abortutils, only: endrun use physics_types, only: phys_te_idx, dyn_te_idx - use physconst, only: cpair, rair + use physconst, only: cpair, rair, latice, latvap use air_composition, only: cpairv, cp_or_cv_dycore ! CCPP-ized subroutine @@ -201,6 +201,8 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & z_ini = state%z_ini(:ncol,:), & count = state%count, & ztodt = ztodt, & + latice = latice, & + latvap = latvap, & vc_physics = vc_physics, & vc_dycore = vc_dycore, & errmsg = errmsg, & From 80d5b86fb3d2018c978642c21902b31af6c56716 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 10 Sep 2024 00:11:10 -0400 Subject: [PATCH 16/89] Build updates; now use check_energy_cam_chng --- src/physics/cam/check_energy_cam.F90 | 7 ++++- src/physics/cam/physpkg.F90 | 42 ++++++++++++++-------------- src/physics/cam7/physpkg.F90 | 39 +++++++++++++------------- src/physics/simple/physpkg.F90 | 11 ++++---- src/physics/spcam/crm_physics.F90 | 4 +-- src/physics/spcam/spcam_drivers.F90 | 7 +++-- 6 files changed, 59 insertions(+), 51 deletions(-) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 4f686b598d..d5ae76ca48 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -171,7 +171,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & scaling_dycore(:ncol,:) = 1.0_r8 else ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:,lchnk) + local_cp_or_cv_dycore(:,:) = local_cp_phys(:,:) scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling end if endif @@ -205,6 +205,11 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & latvap = latvap, & vc_physics = vc_physics, & vc_dycore = vc_dycore, & + name = name, & + flx_vap = flx_vap, & + flx_cnd = flx_cnd, & + flx_ice = flx_ice, & + flx_sen = flx_sen, & errmsg = errmsg, & errflg = errflg & ) diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 227274355e..21e693fa17 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1390,7 +1390,7 @@ subroutine tphysac (ztodt, cam_in, & use aero_model, only: aero_model_drydep use carma_intr, only: carma_emission_tend, carma_timestep_tend use carma_flags_mod, only: carma_do_aerosol, carma_do_emission - use check_energy, only: check_energy_chng, tot_energy_phys + use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun @@ -1615,7 +1615,7 @@ subroutine tphysac (ztodt, cam_in, & call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,& fh2o, surfric, obklen, flx_heat) end if - call check_energy_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) + call check_energy_cam_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) call check_tracers_chng(state, tracerint, "chem_timestep_tend", nstep, ztodt, & cam_in%cflx) end if @@ -1677,9 +1677,9 @@ subroutine tphysac (ztodt, cam_in, & call t_stopf('rayleigh_friction') if (do_clubb_sgs) then - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) else - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & zero, cam_in%shf) endif @@ -1719,7 +1719,7 @@ subroutine tphysac (ztodt, cam_in, & call carma_timestep_tend(state, cam_in, cam_out, ptend, ztodt, pbuf, obklen=obklen, ustar=surfric) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) call t_stopf('carma_timestep_tend') end if @@ -1759,7 +1759,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "gwdrag", nstep, ztodt, zero, & + call check_energy_cam_chng(state, tend, "gwdrag", nstep, ztodt, zero, & zero, zero, flx_heat) call t_stopf('gw_tend') @@ -1789,7 +1789,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) ! Lunar tides call lunar_tides_tend( state, ptend ) @@ -1801,7 +1801,7 @@ subroutine tphysac (ztodt, cam_in, & end if call physics_update(state, ptend, ztodt, tend) ! Check energy integrals - call check_energy_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) ! Ion drag calculation call t_startf ( 'iondrag' ) @@ -1851,7 +1851,7 @@ subroutine tphysac (ztodt, cam_in, & endif ! Check energy integrals - call check_energy_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) call t_stopf ( 'iondrag' ) @@ -1866,7 +1866,7 @@ subroutine tphysac (ztodt, cam_in, & call outfld( 'VTEND_NDG', ptend%v, pcols, lchnk) end if call physics_update(state,ptend,ztodt,tend) - call check_energy_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) endif !-------------- Energy budget checks vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -2257,7 +2257,7 @@ subroutine tphysbc (ztodt, state, & if (.not.dycore_is('EUL')) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if call tot_energy_phys(state, 'phBP') @@ -2385,7 +2385,7 @@ subroutine tphysbc (ztodt, state, & ! Check energy integrals, including "reserved liquid" flx_cnd(:ncol) = prec_dp(:ncol) + rliq(:ncol) snow_dp(:ncol) = snow_dp(:ncol) + rice(:ncol) - call check_energy_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) + call check_energy_cam_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) snow_dp(:ncol) = snow_dp(:ncol) - rice(:ncol) ! @@ -2428,7 +2428,7 @@ subroutine tphysbc (ztodt, state, & end if flx_cnd(:ncol) = prec_sh(:ncol) + rliq2(:ncol) - call check_energy_chng(state, tend, "convect_shallow", nstep, ztodt, zero, flx_cnd, snow_sh, zero) + call check_energy_cam_chng(state, tend, "convect_shallow", nstep, ztodt, zero, flx_cnd, snow_sh, zero) call check_tracers_chng(state, tracerint, "convect_shallow", nstep, ztodt, zero_tracers) @@ -2460,9 +2460,9 @@ subroutine tphysbc (ztodt, state, & ! Before the detrainment, the reserved condensate is all liquid, but if CARMA is doing ! detrainment, then the reserved condensate is snow. if (carma_do_detrain) then - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) else - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) end if end if @@ -2484,7 +2484,7 @@ subroutine tphysbc (ztodt, state, & cam_in%ts, cam_in%sst, zdu) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "cldwat_tend", nstep, ztodt, zero, prec_str, snow_str, zero) + call check_energy_cam_chng(state, tend, "cldwat_tend", nstep, ztodt, zero, prec_str, snow_str, zero) call t_stopf('rk_stratiform_tend') @@ -2556,7 +2556,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "macrop_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "macrop_tend", nstep, ztodt, & zero, flx_cnd(:ncol)/cld_macmic_num_steps, & det_ice(:ncol)/cld_macmic_num_steps, & flx_heat(:ncol)/cld_macmic_num_steps) @@ -2603,7 +2603,7 @@ subroutine tphysbc (ztodt, state, & end if ! Use actual qflux (not lhf/latvap) for consistency with surface fluxes and revised code - call check_energy_chng(state, tend, "clubb_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "clubb_tend", nstep, ztodt, & cam_in%cflx(:ncol,1)/cld_macmic_num_steps, & flx_cnd(:ncol)/cld_macmic_num_steps, & det_ice(:ncol)/cld_macmic_num_steps, & @@ -2704,7 +2704,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state_sc, tend_sc, "microp_tend_subcol", & + call check_energy_cam_chng(state_sc, tend_sc, "microp_tend_subcol", & nstep, ztodt, zero_sc, & prec_str_sc(:state_sc%ncol)/cld_macmic_num_steps, & snow_str_sc(:state_sc%ncol)/cld_macmic_num_steps, zero_sc) @@ -2736,7 +2736,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "microp_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "microp_tend", nstep, ztodt, & zero, prec_str(:ncol)/cld_macmic_num_steps, & snow_str(:ncol)/cld_macmic_num_steps, zero) @@ -2889,7 +2889,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) + call check_energy_cam_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) call t_stopf('radiation') diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index ad5bc9913e..b31a3fcd04 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1644,7 +1644,7 @@ subroutine tphysac (ztodt, cam_in, & call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "clubb_emissions_tend", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "clubb_emissions_tend", nstep, ztodt, zero, zero, zero, zero) call t_stopf('clubb_emissions_tend') @@ -1672,9 +1672,9 @@ subroutine tphysac (ztodt, cam_in, & ! CARMA is doing ! detrainment, then the reserved condensate is snow. if (carma_do_detrain) then - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) else - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) end if end if @@ -1749,7 +1749,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Use actual qflux (not lhf/latvap) for consistency with surface fluxes and revised code - call check_energy_chng(state, tend, "clubb_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "clubb_tend", nstep, ztodt, & cam_in%cflx(:ncol,1)/cld_macmic_num_steps, & flx_cnd(:ncol)/cld_macmic_num_steps, & det_ice(:ncol)/cld_macmic_num_steps, & @@ -1848,7 +1848,7 @@ subroutine tphysac (ztodt, cam_in, & fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state_sc, tend_sc, "microp_tend_subcol", & + call check_energy_cam_chng(state_sc, tend_sc, "microp_tend_subcol", & nstep, ztodt, zero_sc, & prec_str_sc(:state_sc%ncol)/cld_macmic_num_steps, & snow_str_sc(:state_sc%ncol)/cld_macmic_num_steps, zero_sc) @@ -1880,7 +1880,7 @@ subroutine tphysac (ztodt, cam_in, & fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "microp_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "microp_tend", nstep, ztodt, & zero, prec_str(:ncol)/cld_macmic_num_steps, & snow_str(:ncol)/cld_macmic_num_steps, zero) @@ -2036,7 +2036,7 @@ subroutine tphysac (ztodt, cam_in, & fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) + call check_energy_cam_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) call t_stopf('radiation') @@ -2113,7 +2113,7 @@ subroutine tphysac (ztodt, cam_in, & call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,& fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) + call check_energy_cam_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) call check_tracers_chng(state, tracerint, "chem_timestep_tend", nstep, ztodt, & cam_in%cflx) end if @@ -2175,9 +2175,9 @@ subroutine tphysac (ztodt, cam_in, & call t_stopf('rayleigh_friction') if (do_clubb_sgs) then - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) else - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & zero, cam_in%shf) endif @@ -2221,7 +2221,7 @@ subroutine tphysac (ztodt, cam_in, & call carma_timestep_tend(state, cam_in, cam_out, ptend, ztodt, pbuf, obklen=obklen, ustar=surfric) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) call t_stopf('carma_timestep_tend') end if @@ -2260,7 +2260,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "gwdrag", nstep, ztodt, zero, & + call check_energy_cam_chng(state, tend, "gwdrag", nstep, ztodt, zero, & zero, zero, flx_heat) call t_stopf('gw_tend') @@ -2290,7 +2290,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) ! Lunar tides call lunar_tides_tend( state, ptend ) @@ -2302,7 +2302,7 @@ subroutine tphysac (ztodt, cam_in, & end if call physics_update(state, ptend, ztodt, tend) ! Check energy integrals - call check_energy_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) ! Ion drag calculation call t_startf ( 'iondrag' ) @@ -2351,7 +2351,7 @@ subroutine tphysac (ztodt, cam_in, & endif ! Check energy integrals - call check_energy_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) call t_stopf ( 'iondrag' ) @@ -2366,7 +2366,7 @@ subroutine tphysac (ztodt, cam_in, & call outfld( 'VTEND_NDG', ptend%v, pcols, lchnk) end if call physics_update(state,ptend,ztodt,tend) - call check_energy_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) endif !-------------- Energy budget checks vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -2517,7 +2517,8 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend use time_manager, only: is_first_step, get_nstep use convect_diagnostics,only: convect_diagnostics_calc - use check_energy, only: check_energy_chng, check_energy_fix + use check_energy_cam,only: check_energy_cam_chng + use check_energy, only: check_energy_fix use check_energy, only: check_tracers_data, check_tracers_init use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2701,7 +2702,7 @@ subroutine tphysbc (ztodt, state, & if (.not.dycore_is('EUL')) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if @@ -2831,7 +2832,7 @@ subroutine tphysbc (ztodt, state, & ! Check energy integrals, including "reserved liquid" flx_cnd(:ncol) = prec_dp(:ncol) + rliq(:ncol) snow_dp(:ncol) = snow_dp(:ncol) + rice(:ncol) - call check_energy_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) + call check_energy_cam_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) snow_dp(:ncol) = snow_dp(:ncol) - rice(:ncol) !=================================================== diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index 8c9c1586ef..22f1171351 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -503,7 +503,7 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf) use air_composition, only: cpairv, cp_or_cv_dycore use time_manager, only: get_nstep use nudging, only: Nudge_Model, Nudge_ON, nudging_timestep_tend - use check_energy, only: check_energy_chng + use check_energy_cam,only: check_energy_cam_chng ! Arguments ! @@ -595,7 +595,7 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf) if (Nudge_Model .and. Nudge_ON) then call nudging_timestep_tend(state,ptend) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) endif call tot_energy_phys(state, 'phAP') @@ -728,7 +728,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export use cam_history, only: outfld use time_manager, only: get_nstep - use check_energy, only: check_energy_chng, check_energy_fix, check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_chng + use check_energy, only: check_energy_fix, check_energy_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend @@ -833,7 +834,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) if (adiabatic .and. (.not. dycore_is('EUL'))) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if @@ -968,7 +969,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) ! surface flux is computed and supplied as an argument to ! check_energy_chng to account for how the simplified physics forcings are ! changing the total exnergy. - call check_energy_chng(state, tend, "tphysidl", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "tphysidl", nstep, ztodt, zero, zero, zero, zero) if (chem_is_active()) then call t_startf('simple_chem') diff --git a/src/physics/spcam/crm_physics.F90 b/src/physics/spcam/crm_physics.F90 index a1d9d2560d..735d6c3630 100644 --- a/src/physics/spcam/crm_physics.F90 +++ b/src/physics/spcam/crm_physics.F90 @@ -750,7 +750,7 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf, cam_in) use crmx_crm_module, only: crm use crmx_microphysics, only: nmicro_fields use physconst, only: latvap - use check_energy, only: check_energy_chng + use check_energy_cam, only: check_energy_cam_chng use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_lon_all_p, get_lat_all_p use modal_aero_calcsize, only: modal_aero_calcsize_sub use micro_pumas_utils, only: size_dist_param_liq, mg_liq_props, mincld, qsmall @@ -2152,7 +2152,7 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf, cam_in) end if ! check water and energy conservation - call check_energy_chng(state_loc, tend_loc, "crm_tend", nstep, ztodt, zero, & + call check_energy_cam_chng(state_loc, tend_loc, "crm_tend", nstep, ztodt, zero, & prec_dp(:ncol)+(qli_hydro(:ncol,2)-qli_hydro(:ncol,1))/ztodt/1000._r8, & snow_dp(:ncol)+(qi_hydro(:ncol,2)-qi_hydro(:ncol,1))/ztodt/1000._r8, radflux) diff --git a/src/physics/spcam/spcam_drivers.F90 b/src/physics/spcam/spcam_drivers.F90 index ebe6507607..00ab2448bd 100644 --- a/src/physics/spcam/spcam_drivers.F90 +++ b/src/physics/spcam/spcam_drivers.F90 @@ -300,7 +300,8 @@ subroutine tphysbc_spcam (ztodt, state, & use cam_history, only: outfld use constituents, only: pcnst, qmin, cnst_get_ind use time_manager, only: get_nstep - use check_energy, only: check_energy_chng, check_energy_fix + use check_energy_cam,only: check_energy_cam_chng + use check_energy, only: check_energy_fix use check_energy, only: check_tracers_data, check_tracers_init use dycore, only: dycore_is use radiation, only: radiation_tend @@ -443,7 +444,7 @@ subroutine tphysbc_spcam (ztodt, state, & if (dycore_is('LR') .or. dycore_is('SE')) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld('EFIX', flx_heat, pcols,lchnk) end if ! Save state for convective tendency calculations. @@ -557,7 +558,7 @@ subroutine tphysbc_spcam (ztodt, state, & call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "spradheat", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "spradheat", nstep, ztodt, zero, zero, zero, zero) call t_stopf('radiation') From 03209f0918ce253ea326963a9ee56eab1e2bd89c Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 10 Sep 2024 00:16:43 -0400 Subject: [PATCH 17/89] Add missing USE in physbc --- src/physics/cam/physpkg.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 21e693fa17..bab29327b2 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1392,6 +1392,7 @@ subroutine tphysac (ztodt, cam_in, & use carma_flags_mod, only: carma_do_aerosol, carma_do_emission use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng + use check_energy_cam, only: check_energy_cam_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun use dycore, only: dycore_is From 3cc3c3e33cc026cf3148a29a988b59a6d868cf81 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 10 Sep 2024 19:34:41 -0400 Subject: [PATCH 18/89] Fix array oob pcols --- src/physics/cam/check_energy_cam.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index d5ae76ca48..7e1c289b96 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -49,7 +49,7 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) ! handling inside this shim module. (hplin, 9/9/24) if(state%psetcols == pcols) then ! No subcolumns - local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) else if (state%psetcols > pcols) then ! Subcolumns code @@ -148,10 +148,10 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & if(state%psetcols == pcols) then ! No subcolumns - local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling elseif(state%psetcols > pcols) then ! Subcolumns if(.not. all(cpairv(:,:,:) == cpair)) then @@ -164,14 +164,14 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & if (vc_dycore == vc_height) then ! compute cv if vertical coordinate is height: cv = cp - R local_cp_or_cv_dycore(:ncol,:) = cpair-rair - scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling else if (vc_dycore == vc_dry_pressure) then ! SE specific hydrostatic energy local_cp_or_cv_dycore(:ncol,:) = cpair scaling_dycore(:ncol,:) = 1.0_r8 else ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:,:) = local_cp_phys(:,:) + local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling end if endif From f7f4139a6f1333eb80375d6adcfb8a34247b22e3 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 7 Oct 2024 10:56:11 -0600 Subject: [PATCH 19/89] Update atmos_phys to check_energy version --- .gitmodules | 4 +- src/atmos_phys | 2 +- src/physics/cam/cam_diagnostics.F90 | 2 +- src/physics/cam/check_energy.F90 | 164 ++------------------------- src/physics/cam/check_energy_cam.F90 | 164 ++++++++++++++++++++++++++- src/physics/cam/physpkg.F90 | 6 +- src/physics/cam7/physpkg.F90 | 7 +- src/physics/simple/physpkg.F90 | 8 +- src/physics/spcam/spcam_drivers.F90 | 5 +- 9 files changed, 184 insertions(+), 178 deletions(-) diff --git a/.gitmodules b/.gitmodules index 224ee10052..e295d8fec1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,8 +35,8 @@ [submodule "atmos_phys"] path = src/atmos_phys - url = https://github.com/ESCOMP/atmospheric_physics - fxtag = atmos_phys0_05_001 + url = https://github.com/jimmielin/atmospheric_physics + fxtag = df80b9c1 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index f8ce60bf40..df80b9c1e7 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit f8ce60bf40f800623f8eb3065021ec5dfa9e6b45 +Subproject commit df80b9c1e73064f9a0196282a92b66a2041f6a57 diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 97dad2ba01..00d6859a84 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -2019,7 +2019,7 @@ subroutine diag_phys_tend_writeout_dry(state, pbuf, tend, ztodt) ! !--------------------------------------------------------------- - use check_energy, only: check_energy_get_integrals + use check_energy_cam,only: check_energy_get_integrals use physconst, only: cpair ! Arguments diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 5e1df3a967..d71f3df8f6 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -24,13 +24,11 @@ module check_energy use ppgrid, only: pcols, pver, begchunk, endchunk use spmd_utils, only: masterproc - use gmean_mod, only: gmean use physconst, only: gravit, rga, latvap, latice, cpair, rair use air_composition, only: cpairv, cp_or_cv_dycore - use physics_types, only: physics_state, physics_tend, physics_ptend, physics_ptend_init + use physics_types, only: physics_state use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind use cam_logfile, only: iulog - use scamMod, only: single_column, use_camiop, heat_glob_scm use cam_history, only: outfld, write_camiop implicit none @@ -42,10 +40,7 @@ module check_energy ! Public methods public :: check_energy_readnl ! read namelist values public :: check_energy_register ! register fields in physics buffer - public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean public :: check_energy_init ! initialization of module - public :: check_energy_gmean ! global means of physics input and output total energy - public :: check_energy_fix ! add global mean energy difference as a heating public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes @@ -55,13 +50,6 @@ module check_energy logical :: print_energy_errors = .false. - real(r8) :: teout_glob ! global mean energy of output state - real(r8) :: teinp_glob ! global mean energy of input state - real(r8) :: tedif_glob ! global mean energy difference - real(r8) :: psurf_glob ! global mean surface pressure - real(r8) :: ptopb_glob ! global mean top boundary pressure - real(r8) :: heat_glob ! global mean heating rate - ! Physics buffer indices integer, public :: teout_idx = 0 ! teout index in physics buffer @@ -88,6 +76,9 @@ subroutine check_energy_readnl(nlfile) use spmd_utils, only: mpicom, mstrid=>masterprocid, mpi_logical use cam_abortutils, only: endrun + ! update the CCPP-ized namelist option + use check_energy_chng, only: check_energy_chng_init + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input ! Local variables @@ -120,6 +111,9 @@ subroutine check_energy_readnl(nlfile) write(iulog,*) ' print_energy_errors =', print_energy_errors end if + ! update the CCPP-ized namelist option + call check_energy_chng_init(print_energy_errors_in=print_energy_errors) + end subroutine check_energy_readnl !=============================================================================== @@ -154,28 +148,6 @@ subroutine check_energy_register() end subroutine check_energy_register -!=============================================================================== - -subroutine check_energy_get_integrals( tedif_glob_out, heat_glob_out ) - -!----------------------------------------------------------------------- -! Purpose: Return energy integrals -!----------------------------------------------------------------------- - - real(r8), intent(out), optional :: tedif_glob_out - real(r8), intent(out), optional :: heat_glob_out - -!----------------------------------------------------------------------- - - if ( present(tedif_glob_out) ) then - tedif_glob_out = tedif_glob - endif - if ( present(heat_glob_out) ) then - heat_glob_out = heat_glob - endif - -end subroutine check_energy_get_integrals - !================================================================================================ subroutine check_energy_init() @@ -214,128 +186,6 @@ subroutine check_energy_init() end subroutine check_energy_init -!=============================================================================== - - subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) - - use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_get_chunk - use physics_types, only: dyn_te_idx - use cam_history, only: write_camiop -!----------------------------------------------------------------------- -! Compute global mean total energy of physics input and output states -! computed consistently with dynamical core vertical coordinate -! (under hydrostatic assumption) -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state), intent(in ), dimension(begchunk:endchunk) :: state - type(physics_buffer_desc), pointer :: pbuf2d(:,:) - - real(r8), intent(in) :: dtime ! physics time step - integer , intent(in) :: nstep ! current timestep number - -!---------------------------Local storage------------------------------- - integer :: ncol ! number of active columns - integer :: lchnk ! chunk index - - real(r8) :: te(pcols,begchunk:endchunk,4) - ! total energy of input/output states (copy) - real(r8) :: te_glob(4) ! global means of total energy - real(r8), pointer :: teout(:) -!----------------------------------------------------------------------- - - ! Copy total energy out of input and output states - do lchnk = begchunk, endchunk - ncol = state(lchnk)%ncol - ! input energy using dynamical core energy formula - te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) - ! output energy - call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) - - te(:ncol,lchnk,2) = teout(1:ncol) - ! surface pressure for heating rate - te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) - ! model top pressure for heating rate (not constant for z-based vertical coordinate!) - te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) - end do - - ! Compute global means of input and output energies and of - ! surface pressure for heating rate (assume uniform ptop) - call gmean(te, te_glob, 4) - - if (begchunk .le. endchunk) then - teinp_glob = te_glob(1) - teout_glob = te_glob(2) - psurf_glob = te_glob(3) - ptopb_glob = te_glob(4) - - ! Global mean total energy difference - tedif_glob = teinp_glob - teout_glob - heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) - if (masterproc) then - write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & - heat_glob, psurf_glob, ptopb_glob - end if - else - heat_glob = 0._r8 - end if ! (begchunk .le. endchunk) - - end subroutine check_energy_gmean - -!=============================================================================== - subroutine check_energy_fix(state, ptend, nstep, eshflx) - -!----------------------------------------------------------------------- -! Add heating rate required for global mean total energy conservation -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state), intent(in ) :: state - type(physics_ptend), intent(out) :: ptend - - integer , intent(in ) :: nstep ! time step number - real(r8), intent(out ) :: eshflx(pcols) ! effective sensible heat flux - -!---------------------------Local storage------------------------------- - integer :: i ! column - integer :: ncol ! number of atmospheric columns in chunk - integer :: lchnk ! chunk number - real(r8) :: heat_out(pcols) -!----------------------------------------------------------------------- - lchnk = state%lchnk - ncol = state%ncol - - call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) - -#if ( defined OFFLINE_DYN ) - ! disable the energy fix for offline driver - heat_glob = 0._r8 -#endif - - ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs - if (single_column) then - if ( use_camiop) then - heat_glob = heat_glob_scm(1) - else - heat_glob = 0._r8 - endif - endif - ptend%s(:ncol,:pver) = heat_glob - - if (nstep > 0 .and. write_camiop) then - heat_out(:ncol) = heat_glob - call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) - endif - -! compute effective sensible heat flux - do i = 1, ncol - eshflx(i) = heat_glob * (state%pint(i,pver+1) - state%pint(i,1)) * rga - end do - - return - end subroutine check_energy_fix - - !=============================================================================== subroutine check_tracers_init(state, tracerint) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 7e1c289b96..6931cfb3ee 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -1,4 +1,4 @@ -! Shim for CCPP-ized check_energy routines in CAM +! CAM interface for CCPP-ized check_energy routines in CAM module check_energy_cam use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver @@ -8,9 +8,23 @@ module check_energy_cam implicit none private - public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes + public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes public :: check_energy_cam_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes + public :: check_energy_cam_fix ! add heating rate required for global mean total energy conservation + + ! These subroutines cannot be CCPP-ized and replicated from check_energy + public :: check_energy_gmean ! global means of physics input and output total energy + public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean + + ! Module variables used for check_energy_gmean + real(r8) :: teout_glob ! global mean energy of output state + real(r8) :: teinp_glob ! global mean energy of input state + real(r8) :: tedif_glob ! global mean energy difference + real(r8) :: psurf_glob ! global mean surface pressure + real(r8) :: ptopb_glob ! global mean top boundary pressure + real(r8) :: heat_glob ! global mean heating rate + contains ! Compute initial values of energy and water integrals, ! zero cumulative tendencies @@ -215,4 +229,148 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & ) end subroutine check_energy_cam_chng -end module check_energy_cam \ No newline at end of file + + ! Add heating rate required for global mean total energy conservation + subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) + use physics_types, only: physics_ptend, physics_ptend_init + use physconst, only: rga + + ! SCAM support + use scamMod, only: single_column, use_camiop, heat_glob_scm + + ! CCPP-ized subroutine + use check_energy_fix, only: check_energy_fix_run + + type(physics_state), intent(in) :: state + type(physics_ptend), intent(out) :: ptend + + integer , intent(in) :: nstep ! time step number + real(r8), intent(out) :: eshflx(pcols) ! effective sensible heat flux + + integer :: ncol ! number of atmospheric columns in chunk + integer :: lchnk ! chunk number + real(r8) :: heat_out(pcols) + + lchnk = state%lchnk + ncol = state%ncol + + call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) + +#if ( defined OFFLINE_DYN ) + ! disable the energy fix for offline driver + heat_glob = 0._r8 +#endif + + ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs + if (single_column) then + if (use_camiop) then + heat_glob = heat_glob_scm(1) + else + heat_glob = 0._r8 + endif + endif + + if (nstep > 0 .and. write_camiop) then + heat_out(:ncol) = heat_glob + call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) + endif + + ! Call the CCPP-ized subroutine (for non-SCAM) + ! to compute the effective sensible heat flux and save to ptend%s + call check_energy_fix_run( & + ncol = ncol, & + pver = pver, & + pint = state%pint(:ncol,:), & + rga = rga, & + heat_glob = heat_glob. & + ptend_s = ptend%s(:ncol,:), & + eshflx = eshflx(:ncol) & + ) + + end subroutine check_energy_cam_fix + + ! Compute global mean total energy of physics input and output states + ! computed consistently with dynamical core vertical coordinate + ! (under hydrostatic assumption) + ! + ! This subroutine cannot use the CCPP-ized equivalent because + ! it is dependent on chunks. + subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) + use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk + use physics_types, only: dyn_te_idx + use cam_history, only: write_camiop + use ppgrid, only: begchunk, endchunk + use spmd_utils, only: masterproc + use cam_logfile, only: iulog + use gmean_mod, only: gmean + use physconst, only: gravit + + ! To remove, pbuf indices in check_energy + use check_energy, only: teout_idx + + type(physics_state), intent(in), dimension(begchunk:endchunk) :: state + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + + real(r8), intent(in) :: dtime ! physics time step + integer , intent(in) :: nstep ! current timestep number + + integer :: ncol ! number of active columns + integer :: lchnk ! chunk index + + real(r8) :: te(pcols,begchunk:endchunk,4) + ! total energy of input/output states (copy) + real(r8) :: te_glob(4) ! global means of total energy + real(r8), pointer :: teout(:) + + ! Copy total energy out of input and output states + do lchnk = begchunk, endchunk + ncol = state(lchnk)%ncol + ! input energy using dynamical core energy formula + te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) + ! output energy + call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) + + te(:ncol,lchnk,2) = teout(1:ncol) + ! surface pressure for heating rate + te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) + ! model top pressure for heating rate (not constant for z-based vertical coordinate!) + te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) + end do + + ! Compute global means of input and output energies and of + ! surface pressure for heating rate (assume uniform ptop) + call gmean(te, te_glob, 4) + + if (begchunk .le. endchunk) then + teinp_glob = te_glob(1) + teout_glob = te_glob(2) + psurf_glob = te_glob(3) + ptopb_glob = te_glob(4) + + ! Global mean total energy difference + tedif_glob = teinp_glob - teout_glob + heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) + if (masterproc) then + write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & + heat_glob, psurf_glob, ptopb_glob + end if + else + heat_glob = 0._r8 + end if ! (begchunk .le. endchunk) + + end subroutine check_energy_gmean + + ! Return energy integrals (module variables) + subroutine check_energy_get_integrals(tedif_glob_out, heat_glob_out) + real(r8), intent(out), optional :: tedif_glob_out + real(r8), intent(out), optional :: heat_glob_out + + if ( present(tedif_glob_out) ) then + tedif_glob_out = tedif_glob + endif + + if ( present(heat_glob_out) ) then + heat_glob_out = heat_glob + endif + end subroutine check_energy_get_integrals +end module check_energy_cam diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index bab29327b2..25f46c3a45 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1065,7 +1065,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy, only: check_energy_gmean + use check_energy_cam, only: check_energy_gmean use phys_control, only: phys_getopts use spcam_drivers, only: tphysbc_spcam use spmd_utils, only: mpicom @@ -2046,7 +2046,7 @@ subroutine tphysbc (ztodt, state, & use time_manager, only: is_first_step, get_nstep use convect_shallow, only: convect_shallow_tend use check_energy_cam,only: check_energy_cam_timestep_init, check_energy_cam_chng - use check_energy, only: check_energy_fix + use check_energy_cam,only: check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2256,7 +2256,7 @@ subroutine tphysbc (ztodt, state, & call tot_energy_phys(state, 'phBF') call tot_energy_phys(state, 'dyBF',vc=vc_dycore) if (.not.dycore_is('EUL')) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index b31a3fcd04..1ce28d3a93 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1056,7 +1056,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy, only: check_energy_gmean + use check_energy_cam, only: check_energy_gmean use spmd_utils, only: mpicom use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate use cam_history, only: outfld, write_camiop @@ -2517,8 +2517,7 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend use time_manager, only: is_first_step, get_nstep use convect_diagnostics,only: convect_diagnostics_calc - use check_energy_cam,only: check_energy_cam_chng - use check_energy, only: check_energy_fix + use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2700,7 +2699,7 @@ subroutine tphysbc (ztodt, state, & call tot_energy_phys(state, 'dyBF',vc=vc_dycore) if (.not.dycore_is('EUL')) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index 22f1171351..3e594d9073 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -305,7 +305,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics, only: diag_allocate, diag_physvar_ic - use check_energy, only: check_energy_gmean + use check_energy_cam, only: check_energy_gmean use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate ! @@ -728,8 +728,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export use cam_history, only: outfld use time_manager, only: get_nstep - use check_energy_cam, only: check_energy_cam_chng - use check_energy, only: check_energy_fix, check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend @@ -832,7 +832,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) call t_startf('energy_fixer') if (adiabatic .and. (.not. dycore_is('EUL'))) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) diff --git a/src/physics/spcam/spcam_drivers.F90 b/src/physics/spcam/spcam_drivers.F90 index 00ab2448bd..cd7d3f6370 100644 --- a/src/physics/spcam/spcam_drivers.F90 +++ b/src/physics/spcam/spcam_drivers.F90 @@ -300,8 +300,7 @@ subroutine tphysbc_spcam (ztodt, state, & use cam_history, only: outfld use constituents, only: pcnst, qmin, cnst_get_ind use time_manager, only: get_nstep - use check_energy_cam,only: check_energy_cam_chng - use check_energy, only: check_energy_fix + use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use dycore, only: dycore_is use radiation, only: radiation_tend @@ -442,7 +441,7 @@ subroutine tphysbc_spcam (ztodt, state, & call t_startf('energy_fixer') if (dycore_is('LR') .or. dycore_is('SE')) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld('EFIX', flx_heat, pcols,lchnk) From f6f464bb6b73aa52c2850cdb4595ab4148774fc4 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Thu, 10 Oct 2024 16:26:34 -0600 Subject: [PATCH 20/89] Fix build errors -- does not include bld/configure atmos_phys path updates --- src/physics/cam/check_energy.F90 | 2 +- src/physics/cam/check_energy_cam.F90 | 12 ++++++++---- src/physics/simple/physpkg.F90 | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index d71f3df8f6..9f9faa10fe 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -29,7 +29,7 @@ module check_energy use physics_types, only: physics_state use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind use cam_logfile, only: iulog - use cam_history, only: outfld, write_camiop + use cam_history, only: outfld implicit none private diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 6931cfb3ee..e1f143c0c2 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -50,6 +50,7 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) real(r8) :: local_cp_phys(state%psetcols,pver) real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: teout(state%ncol) ! dummy teout argument integer :: lchnk ! chunk identifier integer :: ncol ! number of atmospheric columns character(len=512) :: errmsg @@ -91,6 +92,7 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) ncol = ncol, & pver = pver, & pcnst = pcnst, & + is_first_timestep = is_first_step(), & q = state%q(1:ncol,1:pver,1:pcnst), & pdel = state%pdel(1:ncol,1:pver), & u = state%u(1:ncol,1:pver), & @@ -99,8 +101,6 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) pintdry = state%pintdry(1:ncol,1:pver), & phis = state%phis(1:ncol), & zm = state%zm(1:ncol,:), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & cp_phys = local_cp_phys(1:ncol,:), & cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & @@ -111,7 +111,10 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) tw_cur = state%tw_cur(1:ncol), & tend_te_tnd = tend%te_tnd(1:ncol), & tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & count = state%count, & + teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below vc_physics = vc_physics, & vc_dycore = vc_dycore, & errmsg = errmsg, & @@ -237,6 +240,8 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) ! SCAM support use scamMod, only: single_column, use_camiop, heat_glob_scm + use cam_history, only: write_camiop + use cam_history, only: outfld ! CCPP-ized subroutine use check_energy_fix, only: check_energy_fix_run @@ -282,7 +287,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) pver = pver, & pint = state%pint(:ncol,:), & rga = rga, & - heat_glob = heat_glob. & + heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & eshflx = eshflx(:ncol) & ) @@ -298,7 +303,6 @@ end subroutine check_energy_cam_fix subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk use physics_types, only: dyn_te_idx - use cam_history, only: write_camiop use ppgrid, only: begchunk, endchunk use spmd_utils, only: masterproc use cam_logfile, only: iulog diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index 3e594d9073..eaea0ff1dd 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -729,7 +729,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_history, only: outfld use time_manager, only: get_nstep use check_energy_cam, only: check_energy_cam_chng, check_energy_cam_fix - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend From 2ffa522d8403f73aba0f306a2c35dd50319c33a5 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 14 Oct 2024 12:16:26 -0400 Subject: [PATCH 21/89] Move back to check_energy.F90 for FV3 external compatibility --- src/dynamics/eul/dp_coupling.F90 | 4 +- src/dynamics/fv/dp_coupling.F90 | 4 +- src/dynamics/mpas/dp_coupling.F90 | 4 +- src/dynamics/se/dp_coupling.F90 | 4 +- src/physics/cam/cam_diagnostics.F90 | 2 +- src/physics/cam/check_energy.F90 | 390 ++++++++++++++++++++++++++- src/physics/cam/check_energy_cam.F90 | 380 -------------------------- src/physics/cam/physpkg.F90 | 12 +- src/physics/cam7/physpkg.F90 | 8 +- src/physics/simple/physpkg.F90 | 8 +- src/physics/spcam/crm_physics.F90 | 2 +- src/physics/spcam/spcam_drivers.F90 | 2 +- 12 files changed, 403 insertions(+), 417 deletions(-) delete mode 100644 src/physics/cam/check_energy_cam.F90 diff --git a/src/dynamics/eul/dp_coupling.F90 b/src/dynamics/eul/dp_coupling.F90 index 8e3eb64a21..bc900e2d0e 100644 --- a/src/dynamics/eul/dp_coupling.F90 +++ b/src/dynamics/eul/dp_coupling.F90 @@ -14,7 +14,7 @@ module dp_coupling use physconst, only: cpair, gravit, rair, zvir use air_composition, only: rairv use geopotential, only: geopotential_t - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init #if (defined SPMD) use spmd_dyn, only: buf1, buf1win, buf2, buf2win, & spmdbuf_siz, local_dp_map, & @@ -291,7 +291,7 @@ subroutine d_p_coupling(ps, t3, u3, v3, q3, & ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) end do diff --git a/src/dynamics/fv/dp_coupling.F90 b/src/dynamics/fv/dp_coupling.F90 index af2d13b12e..fc02821471 100644 --- a/src/dynamics/fv/dp_coupling.F90 +++ b/src/dynamics/fv/dp_coupling.F90 @@ -12,7 +12,7 @@ module dp_coupling use physconst, only: gravit, zvir use air_composition, only: cpairv, rairv use geopotential, only: geopotential_t - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init use dynamics_vars, only: T_FVDYCORE_GRID, t_fvdycore_state use dyn_internal_state,only: get_dyn_state use dyn_comp, only: dyn_import_t, dyn_export_t, fv_print_dpcoup_warn @@ -621,7 +621,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do call t_stopf('derived_fields') diff --git a/src/dynamics/mpas/dp_coupling.F90 b/src/dynamics/mpas/dp_coupling.F90 index c312f1e2f9..10d75b4b8c 100644 --- a/src/dynamics/mpas/dp_coupling.F90 +++ b/src/dynamics/mpas/dp_coupling.F90 @@ -413,7 +413,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! MPAS prognostic fields. use geopotential, only: geopotential_t - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init use shr_vmath_mod, only: shr_vmath_log use phys_control, only: waccmx_is use cam_thermo, only: cam_thermo_dry_air_update, cam_thermo_water_update @@ -564,7 +564,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do diff --git a/src/dynamics/se/dp_coupling.F90 b/src/dynamics/se/dp_coupling.F90 index 9de31132a2..919b7f3510 100644 --- a/src/dynamics/se/dp_coupling.F90 +++ b/src/dynamics/se/dp_coupling.F90 @@ -546,7 +546,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) use phys_control, only: waccmx_is use geopotential, only: geopotential_t use static_energy, only: update_dry_static_energy_run - use check_energy_cam,only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init use hycoef, only: hyai, ps0 use shr_vmath_mod, only: shr_vmath_log use qneg_module, only: qneg3 @@ -707,7 +707,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) cpairv(1:ncol,:,lchnk), errflg, errmsg) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do ! lchnk diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 00d6859a84..97dad2ba01 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -2019,7 +2019,7 @@ subroutine diag_phys_tend_writeout_dry(state, pbuf, tend, ztodt) ! !--------------------------------------------------------------- - use check_energy_cam,only: check_energy_get_integrals + use check_energy, only: check_energy_get_integrals use physconst, only: cpair ! Arguments diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9f9faa10fe..f318cb51e1 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -21,37 +21,52 @@ module check_energy !--------------------------------------------------------------------------------- use shr_kind_mod, only: r8 => shr_kind_r8 - use ppgrid, only: pcols, pver, begchunk, endchunk + use ppgrid, only: pcols, pver use spmd_utils, only: masterproc - use physconst, only: gravit, rga, latvap, latice, cpair, rair + use physconst, only: rga use air_composition, only: cpairv, cp_or_cv_dycore use physics_types, only: physics_state use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind use cam_logfile, only: iulog - use cam_history, only: outfld implicit none private -! Public types: + ! Public types: public check_tracers_data -! Public methods - public :: check_energy_readnl ! read namelist values - public :: check_energy_register ! register fields in physics buffer - public :: check_energy_init ! initialization of module - public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes - public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes + ! Public methods - not CCPP-ized + public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes + public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes + public :: tot_energy_phys ! calculate and output total energy and axial angular momentum diagnostics - public :: tot_energy_phys ! calculate and output total energy and axial angular momentum diagnostics + ! These subroutines cannot be CCPP-ized + public :: check_energy_readnl ! read namelist values + public :: check_energy_register ! register fields in physics buffer + public :: check_energy_init ! initialization of module + public :: check_energy_gmean ! global means of physics input and output total energy + public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean -! Private module data + ! Public methods - CAM interfaces to CCPP version: + public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes + public :: check_energy_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes + ! name is retained for FV3 compatibility + public :: check_energy_cam_fix ! add heating rate required for global mean total energy conservation + + ! Private module data logical :: print_energy_errors = .false. -! Physics buffer indices + ! used for check_energy_gmean + real(r8) :: teout_glob ! global mean energy of output state + real(r8) :: teinp_glob ! global mean energy of input state + real(r8) :: tedif_glob ! global mean energy difference + real(r8) :: psurf_glob ! global mean surface pressure + real(r8) :: ptopb_glob ! global mean top boundary pressure + real(r8) :: heat_glob ! global mean heating rate + ! Physics buffer indices integer, public :: teout_idx = 0 ! teout index in physics buffer integer, public :: dtcore_idx = 0 ! dtcore index in physics buffer integer, public :: dqcore_idx = 0 ! dqcore index in physics buffer @@ -542,5 +557,354 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) end subroutine tot_energy_phys + ! Compute global mean total energy of physics input and output states + ! computed consistently with dynamical core vertical coordinate + ! (under hydrostatic assumption) + ! + ! This subroutine cannot use the CCPP-ized equivalent because + ! it is dependent on chunks. + subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) + use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk + use physics_types, only: dyn_te_idx + use ppgrid, only: begchunk, endchunk + use spmd_utils, only: masterproc + use cam_logfile, only: iulog + use gmean_mod, only: gmean + use physconst, only: gravit + + type(physics_state), intent(in), dimension(begchunk:endchunk) :: state + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + + real(r8), intent(in) :: dtime ! physics time step + integer , intent(in) :: nstep ! current timestep number + + integer :: ncol ! number of active columns + integer :: lchnk ! chunk index + + real(r8) :: te(pcols,begchunk:endchunk,4) + ! total energy of input/output states (copy) + real(r8) :: te_glob(4) ! global means of total energy + real(r8), pointer :: teout(:) + + ! Copy total energy out of input and output states + do lchnk = begchunk, endchunk + ncol = state(lchnk)%ncol + ! input energy using dynamical core energy formula + te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) + ! output energy + call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) + + te(:ncol,lchnk,2) = teout(1:ncol) + ! surface pressure for heating rate + te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) + ! model top pressure for heating rate (not constant for z-based vertical coordinate!) + te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) + end do + + ! Compute global means of input and output energies and of + ! surface pressure for heating rate (assume uniform ptop) + call gmean(te, te_glob, 4) + + if (begchunk .le. endchunk) then + teinp_glob = te_glob(1) + teout_glob = te_glob(2) + psurf_glob = te_glob(3) + ptopb_glob = te_glob(4) + + ! Global mean total energy difference + tedif_glob = teinp_glob - teout_glob + heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) + if (masterproc) then + write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & + heat_glob, psurf_glob, ptopb_glob + end if + else + heat_glob = 0._r8 + end if ! (begchunk .le. endchunk) + + end subroutine check_energy_gmean + + ! Return energy integrals (module variables) + subroutine check_energy_get_integrals(tedif_glob_out, heat_glob_out) + real(r8), intent(out), optional :: tedif_glob_out + real(r8), intent(out), optional :: heat_glob_out + + if ( present(tedif_glob_out) ) then + tedif_glob_out = tedif_glob + endif + + if ( present(heat_glob_out) ) then + heat_glob_out = heat_glob + endif + end subroutine check_energy_get_integrals + + ! Compute initial values of energy and water integrals, + ! zero cumulative tendencies + subroutine check_energy_timestep_init(state, tend, pbuf, col_type) + use physics_buffer, only: physics_buffer_desc, pbuf_set_field + use cam_abortutils, only: endrun + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use physics_types, only: physics_tend + use physics_types, only: phys_te_idx, dyn_te_idx + use time_manager, only: is_first_step + use physconst, only: cpair, rair + use air_composition, only: cpairv, cp_or_cv_dycore + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_timestep_init + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + type(physics_buffer_desc), pointer :: pbuf(:) + integer, optional :: col_type ! Flag indicating whether using grid or subcolumns + + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: teout(state%ncol) ! dummy teout argument + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the + ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special + ! handling inside this shim module. (hplin, 9/9/24) + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + else if (state%psetcols > pcols) then + ! Subcolumns code + ! Subcolumns specific error handling + if(.not. all(cpairv(:,:,lchnk) == cpair)) then + call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(1:ncol,:) = cpair + + if (vc_dycore == vc_height) then + ! MPAS specific hydrostatic energy computation (internal energy) + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + else if(vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy (enthalpy) + local_cp_or_cv_dycore(:ncol,:) = cpair + else + ! cp_or_cv is not used in the underlying subroutine, zero it out to be sure + local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 + endif + end if + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_timestep_init( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + is_first_timestep = is_first_step(), & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & + te_ini_dyn = state%te_ini(1:ncol,dyn_te_idx), & + tw_ini = state%tw_ini(1:ncol), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + count = state%count, & + teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + errmsg = errmsg, & + errflg = errflg & + ) + + ! initialize physics buffer + if (is_first_step()) then + call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) + end if + + end subroutine check_energy_timestep_init + + ! Check that the energy and water change matches the boundary fluxes + subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & + flx_vap, flx_cnd, flx_ice, flx_sen) + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use cam_abortutils, only: endrun + use physics_types, only: phys_te_idx, dyn_te_idx + use physics_types, only: physics_tend + use physconst, only: cpair, rair, latice, latvap + use air_composition, only: cpairv, cp_or_cv_dycore + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_run + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + character*(*),intent(in) :: name ! parameterization name for fluxes + integer , intent(in) :: nstep ! current timestep number + real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) + real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) + real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) + real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) + real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: scaling_dycore(state%ncol,pver) + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) + + ! Only if vertical coordinate is vc_height or vc_dry_pressure, cp_or_cv_dycore + ! is nonzero. + if(vc_dycore == vc_height .or. vc_dycore == vc_dry_pressure) then + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + endif + elseif(state%psetcols > pcols) then + ! Subcolumns + if(.not. all(cpairv(:,:,:) == cpair)) then + call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(:,:) = cpair + + ! Note: cp_or_cv set above for pressure coordinate + if (vc_dycore == vc_height) then + ! compute cv if vertical coordinate is height: cv = cp - R + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + else if (vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy + local_cp_or_cv_dycore(:ncol,:) = cpair + scaling_dycore(:ncol,:) = 1.0_r8 + else + ! Moist pressure... use phys formula + local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + end if + endif + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_run( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + scaling_dycore = scaling_dycore(1:ncol,:), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + count = state%count, & + ztodt = ztodt, & + latice = latice, & + latvap = latvap, & + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + name = name, & + flx_vap = flx_vap, & + flx_cnd = flx_cnd, & + flx_ice = flx_ice, & + flx_sen = flx_sen, & + errmsg = errmsg, & + errflg = errflg & + ) + + end subroutine check_energy_cam_chng + + ! Add heating rate required for global mean total energy conservation + subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) + use physics_types, only: physics_ptend, physics_ptend_init + use physconst, only: rga + + ! SCAM support + use scamMod, only: single_column, use_camiop, heat_glob_scm + use cam_history, only: write_camiop + use cam_history, only: outfld + + ! CCPP-ized subroutine + use check_energy_fix, only: check_energy_fix_run + + type(physics_state), intent(in) :: state + type(physics_ptend), intent(out) :: ptend + + integer , intent(in) :: nstep ! time step number + real(r8), intent(out) :: eshflx(pcols) ! effective sensible heat flux + + integer :: ncol ! number of atmospheric columns in chunk + integer :: lchnk ! chunk number + real(r8) :: heat_out(pcols) + + lchnk = state%lchnk + ncol = state%ncol + + call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) + +#if ( defined OFFLINE_DYN ) + ! disable the energy fix for offline driver + heat_glob = 0._r8 +#endif + + ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs + if (single_column) then + if (use_camiop) then + heat_glob = heat_glob_scm(1) + else + heat_glob = 0._r8 + endif + endif + + if (nstep > 0 .and. write_camiop) then + heat_out(:ncol) = heat_glob + call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) + endif + + ! Call the CCPP-ized subroutine (for non-SCAM) + ! to compute the effective sensible heat flux and save to ptend%s + call check_energy_fix_run( & + ncol = ncol, & + pver = pver, & + pint = state%pint(:ncol,:), & + rga = rga, & + heat_glob = heat_glob, & + ptend_s = ptend%s(:ncol,:), & + eshflx = eshflx(:ncol) & + ) + + end subroutine check_energy_cam_fix end module check_energy diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 deleted file mode 100644 index e1f143c0c2..0000000000 --- a/src/physics/cam/check_energy_cam.F90 +++ /dev/null @@ -1,380 +0,0 @@ -! CAM interface for CCPP-ized check_energy routines in CAM -module check_energy_cam - use shr_kind_mod, only: r8 => shr_kind_r8 - use ppgrid, only: pcols, pver - use constituents, only: pcnst - use physics_types, only: physics_state, physics_tend - - implicit none - private - - public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes - public :: check_energy_cam_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes - - public :: check_energy_cam_fix ! add heating rate required for global mean total energy conservation - - ! These subroutines cannot be CCPP-ized and replicated from check_energy - public :: check_energy_gmean ! global means of physics input and output total energy - public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean - - ! Module variables used for check_energy_gmean - real(r8) :: teout_glob ! global mean energy of output state - real(r8) :: teinp_glob ! global mean energy of input state - real(r8) :: tedif_glob ! global mean energy difference - real(r8) :: psurf_glob ! global mean surface pressure - real(r8) :: ptopb_glob ! global mean top boundary pressure - real(r8) :: heat_glob ! global mean heating rate - -contains - ! Compute initial values of energy and water integrals, - ! zero cumulative tendencies - subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) - use physics_buffer, only: physics_buffer_desc, pbuf_set_field - use cam_abortutils, only: endrun - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use physics_types, only: phys_te_idx, dyn_te_idx - use time_manager, only: is_first_step - use physconst, only: cpair, rair - use air_composition, only: cpairv, cp_or_cv_dycore - - ! To remove, pbuf indices in check_energy - use check_energy, only: teout_idx - - ! CCPP-ized subroutine - use check_energy_chng, only: check_energy_chng_timestep_init - - type(physics_state), intent(inout) :: state - type(physics_tend ), intent(inout) :: tend - type(physics_buffer_desc), pointer :: pbuf(:) - integer, optional :: col_type ! Flag indicating whether using grid or subcolumns - - real(r8) :: local_cp_phys(state%psetcols,pver) - real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) - real(r8) :: teout(state%ncol) ! dummy teout argument - integer :: lchnk ! chunk identifier - integer :: ncol ! number of atmospheric columns - character(len=512) :: errmsg - integer :: errflg - - lchnk = state%lchnk - ncol = state%ncol - - ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the - ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special - ! handling inside this shim module. (hplin, 9/9/24) - if(state%psetcols == pcols) then - ! No subcolumns - local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) - local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else if (state%psetcols > pcols) then - ! Subcolumns code - ! Subcolumns specific error handling - if(.not. all(cpairv(:,:,lchnk) == cpair)) then - call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') - endif - - local_cp_phys(1:ncol,:) = cpair - - if (vc_dycore == vc_height) then - ! MPAS specific hydrostatic energy computation (internal energy) - local_cp_or_cv_dycore(:ncol,:) = cpair-rair - else if(vc_dycore == vc_dry_pressure) then - ! SE specific hydrostatic energy (enthalpy) - local_cp_or_cv_dycore(:ncol,:) = cpair - else - ! cp_or_cv is not used in the underlying subroutine, zero it out to be sure - local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 - endif - end if - - ! Call CCPP-ized underlying subroutine. - call check_energy_chng_timestep_init( & - ncol = ncol, & - pver = pver, & - pcnst = pcnst, & - is_first_timestep = is_first_step(), & - q = state%q(1:ncol,1:pver,1:pcnst), & - pdel = state%pdel(1:ncol,1:pver), & - u = state%u(1:ncol,1:pver), & - v = state%v(1:ncol,1:pver), & - T = state%T(1:ncol,1:pver), & - pintdry = state%pintdry(1:ncol,1:pver), & - phis = state%phis(1:ncol), & - zm = state%zm(1:ncol,:), & - cp_phys = local_cp_phys(1:ncol,:), & - cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & - te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & - te_ini_dyn = state%te_ini(1:ncol,dyn_te_idx), & - tw_ini = state%tw_ini(1:ncol), & - te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & - te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & - tw_cur = state%tw_cur(1:ncol), & - tend_te_tnd = tend%te_tnd(1:ncol), & - tend_tw_tnd = tend%tw_tnd(1:ncol), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & - count = state%count, & - teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & - errmsg = errmsg, & - errflg = errflg & - ) - - ! initialize physics buffer - if (is_first_step()) then - call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) - end if - - end subroutine check_energy_cam_timestep_init - - ! Check that the energy and water change matches the boundary fluxes - subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & - flx_vap, flx_cnd, flx_ice, flx_sen) - use cam_thermo, only: get_hydrostatic_energy - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use cam_abortutils, only: endrun - use physics_types, only: phys_te_idx, dyn_te_idx - use physconst, only: cpair, rair, latice, latvap - use air_composition, only: cpairv, cp_or_cv_dycore - - ! CCPP-ized subroutine - use check_energy_chng, only: check_energy_chng_run - - type(physics_state), intent(inout) :: state - type(physics_tend ), intent(inout) :: tend - character*(*),intent(in) :: name ! parameterization name for fluxes - integer , intent(in) :: nstep ! current timestep number - real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) - real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) - real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) - real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) - real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) - - integer :: lchnk ! chunk identifier - integer :: ncol ! number of atmospheric columns - integer :: i ! column index - real(r8) :: local_cp_phys(state%psetcols,pver) - real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) - real(r8) :: scaling_dycore(state%ncol,pver) - character(len=512) :: errmsg - integer :: errflg - - lchnk = state%lchnk - ncol = state%ncol - - if(state%psetcols == pcols) then - ! No subcolumns - local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) - local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - - scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - elseif(state%psetcols > pcols) then - ! Subcolumns - if(.not. all(cpairv(:,:,:) == cpair)) then - call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') - endif - - local_cp_phys(:,:) = cpair - - ! Note: cp_or_cv set above for pressure coordinate - if (vc_dycore == vc_height) then - ! compute cv if vertical coordinate is height: cv = cp - R - local_cp_or_cv_dycore(:ncol,:) = cpair-rair - scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - else if (vc_dycore == vc_dry_pressure) then - ! SE specific hydrostatic energy - local_cp_or_cv_dycore(:ncol,:) = cpair - scaling_dycore(:ncol,:) = 1.0_r8 - else - ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) - scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - end if - endif - - ! Call CCPP-ized underlying subroutine. - call check_energy_chng_run( & - ncol = ncol, & - pver = pver, & - pcnst = pcnst, & - q = state%q(1:ncol,1:pver,1:pcnst), & - pdel = state%pdel(1:ncol,1:pver), & - u = state%u(1:ncol,1:pver), & - v = state%v(1:ncol,1:pver), & - T = state%T(1:ncol,1:pver), & - pintdry = state%pintdry(1:ncol,1:pver), & - phis = state%phis(1:ncol), & - zm = state%zm(1:ncol,:), & - cp_phys = local_cp_phys(1:ncol,:), & - cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & - scaling_dycore = scaling_dycore(1:ncol,:), & - te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & - te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & - tw_cur = state%tw_cur(1:ncol), & - tend_te_tnd = tend%te_tnd(1:ncol), & - tend_tw_tnd = tend%tw_tnd(1:ncol), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & - count = state%count, & - ztodt = ztodt, & - latice = latice, & - latvap = latvap, & - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & - name = name, & - flx_vap = flx_vap, & - flx_cnd = flx_cnd, & - flx_ice = flx_ice, & - flx_sen = flx_sen, & - errmsg = errmsg, & - errflg = errflg & - ) - - end subroutine check_energy_cam_chng - - ! Add heating rate required for global mean total energy conservation - subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) - use physics_types, only: physics_ptend, physics_ptend_init - use physconst, only: rga - - ! SCAM support - use scamMod, only: single_column, use_camiop, heat_glob_scm - use cam_history, only: write_camiop - use cam_history, only: outfld - - ! CCPP-ized subroutine - use check_energy_fix, only: check_energy_fix_run - - type(physics_state), intent(in) :: state - type(physics_ptend), intent(out) :: ptend - - integer , intent(in) :: nstep ! time step number - real(r8), intent(out) :: eshflx(pcols) ! effective sensible heat flux - - integer :: ncol ! number of atmospheric columns in chunk - integer :: lchnk ! chunk number - real(r8) :: heat_out(pcols) - - lchnk = state%lchnk - ncol = state%ncol - - call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) - -#if ( defined OFFLINE_DYN ) - ! disable the energy fix for offline driver - heat_glob = 0._r8 -#endif - - ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs - if (single_column) then - if (use_camiop) then - heat_glob = heat_glob_scm(1) - else - heat_glob = 0._r8 - endif - endif - - if (nstep > 0 .and. write_camiop) then - heat_out(:ncol) = heat_glob - call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) - endif - - ! Call the CCPP-ized subroutine (for non-SCAM) - ! to compute the effective sensible heat flux and save to ptend%s - call check_energy_fix_run( & - ncol = ncol, & - pver = pver, & - pint = state%pint(:ncol,:), & - rga = rga, & - heat_glob = heat_glob, & - ptend_s = ptend%s(:ncol,:), & - eshflx = eshflx(:ncol) & - ) - - end subroutine check_energy_cam_fix - - ! Compute global mean total energy of physics input and output states - ! computed consistently with dynamical core vertical coordinate - ! (under hydrostatic assumption) - ! - ! This subroutine cannot use the CCPP-ized equivalent because - ! it is dependent on chunks. - subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) - use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk - use physics_types, only: dyn_te_idx - use ppgrid, only: begchunk, endchunk - use spmd_utils, only: masterproc - use cam_logfile, only: iulog - use gmean_mod, only: gmean - use physconst, only: gravit - - ! To remove, pbuf indices in check_energy - use check_energy, only: teout_idx - - type(physics_state), intent(in), dimension(begchunk:endchunk) :: state - type(physics_buffer_desc), pointer :: pbuf2d(:,:) - - real(r8), intent(in) :: dtime ! physics time step - integer , intent(in) :: nstep ! current timestep number - - integer :: ncol ! number of active columns - integer :: lchnk ! chunk index - - real(r8) :: te(pcols,begchunk:endchunk,4) - ! total energy of input/output states (copy) - real(r8) :: te_glob(4) ! global means of total energy - real(r8), pointer :: teout(:) - - ! Copy total energy out of input and output states - do lchnk = begchunk, endchunk - ncol = state(lchnk)%ncol - ! input energy using dynamical core energy formula - te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) - ! output energy - call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) - - te(:ncol,lchnk,2) = teout(1:ncol) - ! surface pressure for heating rate - te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) - ! model top pressure for heating rate (not constant for z-based vertical coordinate!) - te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) - end do - - ! Compute global means of input and output energies and of - ! surface pressure for heating rate (assume uniform ptop) - call gmean(te, te_glob, 4) - - if (begchunk .le. endchunk) then - teinp_glob = te_glob(1) - teout_glob = te_glob(2) - psurf_glob = te_glob(3) - ptopb_glob = te_glob(4) - - ! Global mean total energy difference - tedif_glob = teinp_glob - teout_glob - heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) - if (masterproc) then - write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & - heat_glob, psurf_glob, ptopb_glob - end if - else - heat_glob = 0._r8 - end if ! (begchunk .le. endchunk) - - end subroutine check_energy_gmean - - ! Return energy integrals (module variables) - subroutine check_energy_get_integrals(tedif_glob_out, heat_glob_out) - real(r8), intent(out), optional :: tedif_glob_out - real(r8), intent(out), optional :: heat_glob_out - - if ( present(tedif_glob_out) ) then - tedif_glob_out = tedif_glob - endif - - if ( present(heat_glob_out) ) then - heat_glob_out = heat_glob - endif - end subroutine check_energy_get_integrals -end module check_energy_cam diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 25f46c3a45..1d431b2dbb 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1065,7 +1065,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy_cam, only: check_energy_gmean + use check_energy, only: check_energy_gmean use phys_control, only: phys_getopts use spcam_drivers, only: tphysbc_spcam use spmd_utils, only: mpicom @@ -1392,7 +1392,7 @@ subroutine tphysac (ztodt, cam_in, & use carma_flags_mod, only: carma_do_aerosol, carma_do_emission use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng - use check_energy_cam, only: check_energy_cam_chng + use check_energy, only: check_energy_cam_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun use dycore, only: dycore_is @@ -2045,8 +2045,8 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend, convect_deep_tend_2, deep_scheme_does_scav_trans use time_manager, only: is_first_step, get_nstep use convect_shallow, only: convect_shallow_tend - use check_energy_cam,only: check_energy_cam_timestep_init, check_energy_cam_chng - use check_energy_cam,only: check_energy_cam_fix + use check_energy, only: check_energy_timestep_init, check_energy_cam_chng + use check_energy, only: check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2257,7 +2257,9 @@ subroutine tphysbc (ztodt, state, & call tot_energy_phys(state, 'dyBF',vc=vc_dycore) if (.not.dycore_is('EUL')) then call check_energy_cam_fix(state, ptend, nstep, flx_heat) + call physics_update(state, ptend, ztodt, tend) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if @@ -2632,7 +2634,7 @@ subroutine tphysbc (ztodt, state, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 1ce28d3a93..ead4935939 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1056,7 +1056,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy_cam, only: check_energy_gmean + use check_energy, only: check_energy_gmean use spmd_utils, only: mpicom use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate use cam_history, only: outfld, write_camiop @@ -1366,7 +1366,7 @@ subroutine tphysac (ztodt, cam_in, & use aoa_tracers, only: aoa_tracers_timestep_tend use physconst, only: rhoh2o use aero_model, only: aero_model_drydep - use check_energy_cam, only: check_energy_cam_timestep_init, check_energy_cam_chng + use check_energy, only: check_energy_timestep_init, check_energy_cam_chng use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use time_manager, only: get_nstep @@ -1775,7 +1775,7 @@ subroutine tphysac (ztodt, cam_in, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then @@ -2517,7 +2517,7 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend use time_manager, only: is_first_step, get_nstep use convect_diagnostics,only: convect_diagnostics_calc - use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use check_energy, only: tot_energy_phys use dycore, only: dycore_is diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index eaea0ff1dd..c236f7f021 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -305,7 +305,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics, only: diag_allocate, diag_physvar_ic - use check_energy_cam, only: check_energy_gmean + use check_energy, only: check_energy_gmean use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate ! @@ -503,7 +503,7 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf) use air_composition, only: cpairv, cp_or_cv_dycore use time_manager, only: get_nstep use nudging, only: Nudge_Model, Nudge_ON, nudging_timestep_tend - use check_energy_cam,only: check_energy_cam_chng + use check_energy, only: check_energy_cam_chng ! Arguments ! @@ -728,8 +728,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export use cam_history, only: outfld use time_manager, only: get_nstep - use check_energy_cam, only: check_energy_cam_chng, check_energy_cam_fix - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend diff --git a/src/physics/spcam/crm_physics.F90 b/src/physics/spcam/crm_physics.F90 index 735d6c3630..8812d2be72 100644 --- a/src/physics/spcam/crm_physics.F90 +++ b/src/physics/spcam/crm_physics.F90 @@ -750,7 +750,7 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf, cam_in) use crmx_crm_module, only: crm use crmx_microphysics, only: nmicro_fields use physconst, only: latvap - use check_energy_cam, only: check_energy_cam_chng + use check_energy, only: check_energy_cam_chng use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_lon_all_p, get_lat_all_p use modal_aero_calcsize, only: modal_aero_calcsize_sub use micro_pumas_utils, only: size_dist_param_liq, mg_liq_props, mincld, qsmall diff --git a/src/physics/spcam/spcam_drivers.F90 b/src/physics/spcam/spcam_drivers.F90 index cd7d3f6370..b9f7a596cc 100644 --- a/src/physics/spcam/spcam_drivers.F90 +++ b/src/physics/spcam/spcam_drivers.F90 @@ -300,7 +300,7 @@ subroutine tphysbc_spcam (ztodt, state, & use cam_history, only: outfld use constituents, only: pcnst, qmin, cnst_get_ind use time_manager, only: get_nstep - use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use dycore, only: dycore_is use radiation, only: radiation_tend From 4b6de4306cce342c6eab46333004e63d4afcb989 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 15 Oct 2024 12:47:16 -0400 Subject: [PATCH 22/89] Fix subcol test with FV dycore --- src/physics/cam/check_energy.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index f318cb51e1..998fbb9e18 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -801,9 +801,9 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & local_cp_or_cv_dycore(:ncol,:) = cpair scaling_dycore(:ncol,:) = 1.0_r8 else - ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) - scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + ! Moist pressure... use phys formula, cp_or_cv_dycore is unused. Reset for safety + local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 + scaling_dycore(:ncol,:) = 0.0_r8 end if endif From cfd28249446085affc8674beccfe642a771559a7 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Fri, 25 Oct 2024 12:23:38 -0600 Subject: [PATCH 23/89] Small updates to comments and indenting --- src/physics/cam/clubb_intr.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index aedfa22fbd..7beb445b37 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2743,7 +2743,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_get_field(pbuf, naai_idx, naai) end if - ! Initialize physics tendency arrays, copy the state to state1 array to use in this routine + ! Initialize physics tendency arrays call physics_ptend_init(ptend_all, state%psetcols, 'clubb') ! Copy the state to state1 array to use in this routine @@ -2845,7 +2845,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected endif - ! Initialize the apply_const variable (note special logic is due to eularian backstepping) + ! Initialize the apply_const variable (note special logic is due to eulerian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then apply_const = 0._r8 ! On first time through do not remove constant ! from moments since it has not been added yet @@ -4111,7 +4111,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do i=1, ncol clubbtop(i) = top_lev do while ((rtp2(i,clubbtop(i)) <= 1.e-15_r8 .and. rcm(i,clubbtop(i)) == 0._r8) .and. clubbtop(i) < pver) - clubbtop(i) = clubbtop(i) + 1 + clubbtop(i) = clubbtop(i) + 1 end do end do From d924e4e434929aa47a89d875e80b7974ce1cdee5 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Wed, 23 Oct 2024 13:19:24 -0400 Subject: [PATCH 24/89] Update atmos_phys; move energy formula to cam_thermo_formula; write cp_or_cv_dycore to snapshot --- .gitmodules | 2 +- src/atmos_phys | 2 +- src/control/cam_snapshot_common.F90 | 9 ++++- src/physics/cam/check_energy.F90 | 56 +++++++++++++++-------------- src/utils/cam_thermo_formula.F90 | 14 ++++++++ 5 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 src/utils/cam_thermo_formula.F90 diff --git a/.gitmodules b/.gitmodules index e295d8fec1..0edbb78972 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/jimmielin/atmospheric_physics - fxtag = df80b9c1 + fxtag = 952ebdd fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index df80b9c1e7..952ebddfa2 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit df80b9c1e73064f9a0196282a92b66a2041f6a57 +Subproject commit 952ebddfa22dd796578fba8d73db6128c8db88c1 diff --git a/src/control/cam_snapshot_common.F90 b/src/control/cam_snapshot_common.F90 index ffae561370..fa558b3ad2 100644 --- a/src/control/cam_snapshot_common.F90 +++ b/src/control/cam_snapshot_common.F90 @@ -81,7 +81,7 @@ module cam_snapshot_common integer :: cam_snapshot_before_num, cam_snapshot_after_num ! Note the maximum number of variables for each type -type (snapshot_type) :: state_snapshot(29) +type (snapshot_type) :: state_snapshot(30) type (snapshot_type) :: cnst_snapshot(pcnst) type (snapshot_type) :: tend_snapshot(6) type (snapshot_type) :: cam_in_snapshot(30) @@ -283,6 +283,9 @@ subroutine cam_state_snapshot_init(cam_snapshot_before_num_in, cam_snapshot_afte call snapshot_addfld( nstate_var, state_snapshot, cam_snapshot_before_num, cam_snapshot_after_num, & 'state%te_cur_dyn', 'state_te_cur_dyn', 'unset', horiz_only) + call snapshot_addfld( nstate_var, state_snapshot, cam_snapshot_before_num, cam_snapshot_after_num, & + 'air_composition_cp_or_cv_dycore', 'cp_or_cv_dycore', 'J kg-1 K-1', 'lev') + end subroutine cam_state_snapshot_init subroutine cam_cnst_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) @@ -741,6 +744,7 @@ end subroutine snapshot_addfld subroutine state_snapshot_all_outfld(lchnk, file_num, state) use physics_types, only: phys_te_idx, dyn_te_idx + use air_composition, only: cp_or_cv_dycore integer, intent(in) :: lchnk integer, intent(in) :: file_num @@ -843,6 +847,9 @@ subroutine state_snapshot_all_outfld(lchnk, file_num, state) case ('state%te_cur_dyn') call outfld(state_snapshot(i)%standard_name, state%te_cur(:, dyn_te_idx), pcols, lchnk) + case ('air_composition_cp_or_cv_dycore') + call outfld(state_snapshot(i)%standard_name, cp_or_cv_dycore(:,:,lchnk), pcols, lchnk) + case default call endrun('ERROR in state_snapshot_all_outfld: no match found for '//trim(state_snapshot(i)%ddt_string)) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 998fbb9e18..774764c563 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -415,7 +415,8 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) use cam_thermo, only: get_hydrostatic_energy,thermo_budget_num_vars,thermo_budget_vars, & wvidx,wlidx,wiidx,seidx,poidx,keidx,moidx,mridx,ttidx,teidx use cam_history, only: outfld - use dyn_tests_utils, only: vc_physics, vc_height, vc_dry_pressure + use dyn_tests_utils, only: vc_physics + use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS use cam_abortutils, only: endrun use cam_history_support, only: max_fieldname_len @@ -467,7 +468,7 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) end if if (state%psetcols == pcols) then - if (vc_loc == vc_height .or. vc_loc == vc_dry_pressure) then + if (vc_loc == ENERGY_FORMULA_DYCORE_MPAS .or. vc_loc == ENERGY_FORMULA_DYCORE_SE) then cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) else cp_or_cv(:ncol,:) = cpairv(:ncol,:,lchnk) @@ -476,7 +477,7 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) call endrun('tot_energy_phys: energy diagnostics not implemented/tested for subcolumns') end if - if (vc_loc == vc_height .or. vc_loc == vc_dry_pressure) then + if (vc_loc == ENERGY_FORMULA_DYCORE_MPAS .or. vc_loc == ENERGY_FORMULA_DYCORE_SE) then scaling(:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv(:ncol,:)!scaling for energy consistency else scaling(:ncol,:) = 1.0_r8 !internal energy / enthalpy same as CAM physics @@ -643,7 +644,8 @@ end subroutine check_energy_get_integrals subroutine check_energy_timestep_init(state, tend, pbuf, col_type) use physics_buffer, only: physics_buffer_desc, pbuf_set_field use cam_abortutils, only: endrun - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use dyn_tests_utils, only: vc_physics, vc_dycore + use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS use physics_types, only: physics_tend use physics_types, only: phys_te_idx, dyn_te_idx use time_manager, only: is_first_step @@ -671,7 +673,7 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type) ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special - ! handling inside this shim module. (hplin, 9/9/24) + ! handling inside this CAM interface. (hplin, 9/9/24) if(state%psetcols == pcols) then ! No subcolumns local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) @@ -685,10 +687,10 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type) local_cp_phys(1:ncol,:) = cpair - if (vc_dycore == vc_height) then + if (vc_dycore == ENERGY_FORMULA_DYCORE_MPAS) then ! MPAS specific hydrostatic energy computation (internal energy) local_cp_or_cv_dycore(:ncol,:) = cpair-rair - else if(vc_dycore == vc_dry_pressure) then + else if(vc_dycore == ENERGY_FORMULA_DYCORE_SE) then ! SE specific hydrostatic energy (enthalpy) local_cp_or_cv_dycore(:ncol,:) = cpair else @@ -721,12 +723,12 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type) tw_cur = state%tw_cur(1:ncol), & tend_te_tnd = tend%te_tnd(1:ncol), & tend_tw_tnd = tend%tw_tnd(1:ncol), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & count = state%count, & teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & + energy_formula_physics = vc_physics, & + energy_formula_dycore = vc_dycore, & errmsg = errmsg, & errflg = errflg & ) @@ -741,15 +743,16 @@ end subroutine check_energy_timestep_init ! Check that the energy and water change matches the boundary fluxes subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & flx_vap, flx_cnd, flx_ice, flx_sen) - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use cam_abortutils, only: endrun - use physics_types, only: phys_te_idx, dyn_te_idx - use physics_types, only: physics_tend - use physconst, only: cpair, rair, latice, latvap - use air_composition, only: cpairv, cp_or_cv_dycore + use dyn_tests_utils, only: vc_physics, vc_dycore + use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS + use cam_abortutils, only: endrun + use physics_types, only: phys_te_idx, dyn_te_idx + use physics_types, only: physics_tend + use physconst, only: cpair, rair, latice, latvap + use air_composition, only: cpairv, cp_or_cv_dycore ! CCPP-ized subroutine - use check_energy_chng, only: check_energy_chng_run + use check_energy_chng, only: check_energy_chng_run type(physics_state), intent(inout) :: state type(physics_tend ), intent(inout) :: tend @@ -776,9 +779,8 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & ! No subcolumns local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) - ! Only if vertical coordinate is vc_height or vc_dry_pressure, cp_or_cv_dycore - ! is nonzero. - if(vc_dycore == vc_height .or. vc_dycore == vc_dry_pressure) then + ! Only if using MPAS or SE energy formula cp_or_cv_dycore is nonzero. + if(vc_dycore == ENERGY_FORMULA_DYCORE_MPAS .or. vc_dycore == ENERGY_FORMULA_DYCORE_SE) then local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling @@ -792,11 +794,11 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & local_cp_phys(:,:) = cpair ! Note: cp_or_cv set above for pressure coordinate - if (vc_dycore == vc_height) then + if (vc_dycore == ENERGY_FORMULA_DYCORE_MPAS) then ! compute cv if vertical coordinate is height: cv = cp - R local_cp_or_cv_dycore(:ncol,:) = cpair-rair scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - else if (vc_dycore == vc_dry_pressure) then + else if (vc_dycore == ENERGY_FORMULA_DYCORE_SE) then ! SE specific hydrostatic energy local_cp_or_cv_dycore(:ncol,:) = cpair scaling_dycore(:ncol,:) = 1.0_r8 @@ -832,10 +834,10 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & z_ini = state%z_ini(:ncol,:), & count = state%count, & ztodt = ztodt, & - latice = latice, & - latvap = latvap, & - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & + latice = latice, & + latvap = latvap, & + energy_formula_physics = vc_physics, & + energy_formula_dycore = vc_dycore, & name = name, & flx_vap = flx_vap, & flx_cnd = flx_cnd, & diff --git a/src/utils/cam_thermo_formula.F90 b/src/utils/cam_thermo_formula.F90 new file mode 100644 index 0000000000..7781e9da9c --- /dev/null +++ b/src/utils/cam_thermo_formula.F90 @@ -0,0 +1,14 @@ +module cam_thermo_formula + + implicit none + private + save + + ! energy_formula options for use by CCPPized check_energy + integer, public, parameter :: ENERGY_FORMULA_DYCORE_FV = 0 ! vc_moist_pressure + integer, public, parameter :: ENERGY_FORMULA_DYCORE_SE = 1 ! vc_dry_pressure + integer, public, parameter :: ENERGY_FORMULA_DYCORE_MPAS = 2 ! vc_height + + !REMOVECAM: in CAM, energy_formula_physics and energy_formula_dycore still uses vc_physics + ! and vc_dycore in dyn_tests_utils. The values are the same. +end module cam_thermo_formula From 46b82279c76644b410979b327dabb813afee01a7 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 28 Oct 2024 11:09:15 -0400 Subject: [PATCH 25/89] Update external to fix bug; ChangeLog draft --- .gitmodules | 2 +- doc/ChangeLog | 72 +++++++++++++++++++++++++++++++++++++++++++++++--- src/atmos_phys | 2 +- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0edbb78972..e74baf681e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/jimmielin/atmospheric_physics - fxtag = 952ebdd + fxtag = 44d724d fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/doc/ChangeLog b/doc/ChangeLog index 8294c223f2..f9aded72d5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,71 @@ =============================================================== +Tag name: +Originator(s): jimmielin +Date: 25 Oct 2024 +One-line Summary: Implement CCPPized check_energy_chng and check_energy_fix +Github PR URL: https://github.com/ESCOMP/CAM/pull/1180 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): +- CCPPize check_energy_chng and check_energy_fix (https://github.com/ESCOMP/CAM/issues/1138) + CAM interfaces have been kept in check_energy.F90 instead of a new module because check_tracers is not yet CCPPized, there are other non-CCPPized routines in module, and for compatibility with FV3 external calls +- Save air_composition cp_or_cv_dycore into state snapshot +- Separate out "energy_formula_physics"/"energy_formula_dycore" definitions used in get_hydrostatic_energy from dyn_tests_utils "vcoord" for an eventual change in SIMA. + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: N/A + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: + +List all files eliminated: N/A + +List all files added and what they do: +- separate out energy formula definitions used in get_hydrostatic_energy from dyn_tests_utils "vcoord" +A src/utils/cam_thermo_formula.F90 + +List all existing files that have been modified, and describe the changes: + +Update atmos_phys external with CCPPized check_energy +M .gitmodules +M bld/configure +M src/atmos_phys + +Save cp_or_cv_dycore in state snapshot +M src/control/cam_snapshot_common.F90 + +New CAM interfaces to CCPPized routines, when avaialble +M src/physics/cam/check_energy.F90 + +Update calls to CCPPized routines, when available +M src/physics/cam/physpkg.F90 +M src/physics/cam/zm_conv_intr.F90 +M src/physics/cam7/physpkg.F90 +M src/physics/simple/physpkg.F90 +M src/physics/spcam/crm_physics.F90 +M src/physics/spcam/spcam_drivers.F90 + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + +Summarize any changes to answers: B4B + +=============================================================== + Tag name: cam6_4_043 Originator(s): eaton Date: 25 Oct 2024 @@ -31,12 +97,12 @@ Describe any changes made to the namelist: . change default value of seasalt_emis_scale to 0.75 for cam7 (both lt and mt) This is a cam7 tuning mod from issue #1143 -. update ubc_file_path for cam7 (lt only) to +. update ubc_file_path for cam7 (lt only) to atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.1849-2014_c240604.nc List any changes to the defaults for the boundary datasets: -. update ubc_file_path for cam7 (lt only) to +. update ubc_file_path for cam7 (lt only) to atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.1849-2014_c240604.nc Describe any substantial timing or memory changes: none @@ -64,7 +130,7 @@ bld/namelist_files/namelist_defaults_cam.xml This is a cam7 tuning mod from issue #1143 bld/namelist_files/use_cases/1850_cam_lt.xml -. update ubc_file_path to +. update ubc_file_path to atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.1849-2014_c240604.nc cime_config/testdefs/testlist_cam.xml diff --git a/src/atmos_phys b/src/atmos_phys index 952ebddfa2..44d724d8e8 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 952ebddfa22dd796578fba8d73db6128c8db88c1 +Subproject commit 44d724d8e88ab0b910543a9fdecd24fea9ca62f7 From 75f51d1331238b00228c2f0d5ea1086ddb2ebfa8 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Mon, 28 Oct 2024 15:21:02 -0600 Subject: [PATCH 26/89] Making nzm_clubb and nzt_clubb module parameters that are initialized in clubb_ini_cam. Reusing inv_exner_clubb(:,pver) to set inv_exner_clubb_surf. Splitting up array initialization loop to slightly improve CPU performance. --- src/physics/cam/clubb_intr.F90 | 45 ++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 7beb445b37..6fa4fa2936 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -58,6 +58,10 @@ module clubb_intr type (sclr_idx_type) :: & sclr_idx + + integer :: & + nzm_clubb, & + nzt_clubb #endif private @@ -1509,6 +1513,11 @@ subroutine clubb_ini_cam(pbuf2d) call endrun('clubb_ini_cam: CLUBB library core_rknd must match CAM r8 and it does not') end if + ! Determine number of vertical levels used in clubb, thermo variables are nzt_clubb + ! and momentum variables are nzm_clubb + nzt_clubb = pver + 1 - top_lev + nzm_clubb = pverp + 1 - top_lev + ! Allocate PDF parameters across columns and chunks allocate( & pdf_params_chnk(begchunk:endchunk), & @@ -1746,11 +1755,11 @@ subroutine clubb_ini_cam(pbuf2d) ! at each time step, which is why dummy arrays are read in here for heights ! as they are immediately overwrote. !$OMP PARALLEL - call check_clubb_settings_api( pverp+1-top_lev, clubb_params_single_col, & ! Intent(in) - l_implemented, & ! Intent(in) - l_input_fields, & ! Intent(in) - clubb_config_flags, & ! intent(in) - err_code ) ! Intent(out) + call check_clubb_settings_api( nzm_clubb, clubb_params_single_col, & ! Intent(in) + l_implemented, & ! Intent(in) + l_input_fields, & ! Intent(in) + clubb_config_flags, & ! intent(in) + err_code ) ! Intent(out) if ( err_code == clubb_fatal_error ) then call endrun('clubb_ini_cam: FATAL ERROR CALLING SETUP_CLUBB_CORE') @@ -1885,7 +1894,7 @@ subroutine clubb_ini_cam(pbuf2d) if (stats_metadata%l_stats) then call stats_init_clubb( .true., dum1, dum2, & - pverp+1-top_lev, pverp+1-top_lev, pverp+1-top_lev, dum3, & + nzm_clubb, nzm_clubb, nzm_clubb, dum3, & stats_zt(:), stats_zm(:), stats_sfc(:), & stats_rad_zt(:), stats_rad_zm(:)) @@ -2237,7 +2246,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Local CLUBB variables dimensioned as NCOL (only useful columns) to be sent into the clubb run api ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES - real(r8), dimension(state%ncol,pverp+1-top_lev) :: & + real(r8), dimension(state%ncol,nzm_clubb) :: & thlm_forcing, & ! theta_l forcing (thermodynamic levels) [K/s] rtm_forcing, & ! r_t forcing (thermodynamic levels) [(kg/kg)/s] um_forcing, & ! u wind forcing (thermodynamic levels) [m/s/s] @@ -2337,7 +2346,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Local CLUBB variables dimensioned as NCOL (only useful columns) to be sent into the clubb run api ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES - real(r8), dimension(state%ncol,pverp+1-top_lev,sclr_dim) :: & + real(r8), dimension(state%ncol,nzm_clubb,sclr_dim) :: & sclrm_forcing, & ! Passive scalar forcing [{units vary}/s] sclrm, & ! Passive scalar mean (thermo. levels) [units vary] sclrp2, & ! sclr'^2 (momentum levels) [{units vary}^2] @@ -2347,13 +2356,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpsclrp, & ! w'sclr' (momentum levels) [{units vary} m/s] sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] - real(r8), dimension(state%ncol,pverp+1-top_lev,edsclr_dim) :: & + real(r8), dimension(state%ncol,nzm_clubb,edsclr_dim) :: & edsclrm_forcing, & ! Eddy passive scalar forcing [{units vary}/s] edsclr_in ! Scalars to be diffused through CLUBB [units vary] ! Local CLUBB variables dimensioned as NCOL (only useful columns) to be sent into the clubb run api ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES - real(r8), dimension(state%ncol,pverp+1-top_lev,hydromet_dim) :: & + real(r8), dimension(state%ncol,nzm_clubb,hydromet_dim) :: & hydromet, & wphydrometp, & wp2hmp, & @@ -2404,7 +2413,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: rrho(pcols) ! Inverse of air density [1/kg/m^3] real(r8) :: kinwat(pcols) ! Kinematic water vapor flux [m/s] real(r8) :: latsub - real(r8) :: thlp2_rad_out(pcols,pverp+1-top_lev) + real(r8) :: thlp2_rad_out(pcols,nzm_clubb) real(r8) :: apply_const, rtm_test real(r8) :: dl_rad, di_rad, dt_low @@ -2602,8 +2611,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & clubb_params ! Adjustable CLUBB parameters (C1, C2 ...) integer :: & - nzm_clubb, & - nzt_clubb, & sclr, & edsclr, & n @@ -2766,11 +2773,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ncol = state%ncol lchnk = state%lchnk - ! Determine number of vertical levels used in clubb, thermo variables are nzt_clubb - ! and momentum variables are nzm_clubb - nzt_clubb = pver + 1 - top_lev - nzm_clubb = pverp + 1 - top_lev - ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then call init_pdf_params_api( nzm_clubb, ncol, pdf_params_chnk(lchnk) ) @@ -2988,7 +2990,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_ref(i,k) = 0.0_r8 ug(i,k) = 0.0_r8 vg(i,k) = 0.0_r8 + end do + end do + !$acc parallel loop gang vector collapse(2) default(present) + do k = 1, nzm_clubb + do i = 1, ncol ! Perturbed winds are not used in CAM um_pert_inout(i,k) = 0.0_r8 vm_pert_inout(i,k) = 0.0_r8 @@ -3275,7 +3282,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute exner at the surface for converting the sensible heat fluxes ! to a flux of potential temperature for use as clubb's boundary conditions - inv_exner_clubb_surf(i) = 1._r8 / ( ( state1%pmid(i,pver) / p0_clubb )**( rairv(i,pver,lchnk) / cpairv(i,pver,lchnk) ) ) + inv_exner_clubb_surf(i) = inv_exner_clubb(i,pver) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. From 9dd22853e4992dfd5f7b6ac0c0bdca682becd9c0 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Tue, 29 Oct 2024 11:48:13 -0400 Subject: [PATCH 27/89] add test --- cime_config/testdefs/testlist_cam.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index caf4a0ae37..dcb1652862 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -1752,6 +1752,15 @@ + + + + + + + + + From aa274e78633272bc60520ca6871fd0479a2a1621 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Tue, 29 Oct 2024 18:21:55 -0400 Subject: [PATCH 28/89] add QPC7 --- .../use_cases/aquaplanet_cam7.xml | 48 +++++++++++++++++++ cime_config/config_component.xml | 1 + cime_config/config_compsets.xml | 5 ++ 3 files changed, 54 insertions(+) create mode 100644 bld/namelist_files/use_cases/aquaplanet_cam7.xml diff --git a/bld/namelist_files/use_cases/aquaplanet_cam7.xml b/bld/namelist_files/use_cases/aquaplanet_cam7.xml new file mode 100644 index 0000000000..a7be0ebf7b --- /dev/null +++ b/bld/namelist_files/use_cases/aquaplanet_cam7.xml @@ -0,0 +1,48 @@ + + + + + + +0. +0. +0. +fixed_parameters + + + false + + +1.650e-6 +0.306e-6 +348.0e-6 + + +atm/cam/solar/ape_solar_ave_tsi_1365.nc + + +apeozone_cam3_5_54.nc +atm/cam/ozone +OZONE +CYCLICAL +1990 + + +86164.10063718943 +6.37100e6 +9.79764 +28.96623324623746 +18.01618112892741 +1.846e3 + +.false. + +.true. +.true. + "" + "" + "" + + 0.0 + + diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 76fe7858db..a4fd3b11bf 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -255,6 +255,7 @@ aquaplanet_cam6 aquaplanet_cam6 aquaplanet_rce_cam6 + aquaplanet_cam7 aquaplanet_waccm_2000 2010_cam6 diff --git a/cime_config/config_compsets.xml b/cime_config/config_compsets.xml index c04f925dda..917df56bc5 100644 --- a/cime_config/config_compsets.xml +++ b/cime_config/config_compsets.xml @@ -291,6 +291,11 @@ + + QPC7 + 2000_CAM70_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV + + QPC2000climo 2000_CAM60%CT1S_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV From 08abb12faba67214d87a3c7859f0ae826df4aaad Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Tue, 29 Oct 2024 18:41:11 -0400 Subject: [PATCH 29/89] add %LT to QPC7 spec --- cime_config/config_component.xml | 2 +- cime_config/config_compsets.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index a4fd3b11bf..0b39ec4b08 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -255,7 +255,7 @@ aquaplanet_cam6 aquaplanet_cam6 aquaplanet_rce_cam6 - aquaplanet_cam7 + aquaplanet_cam7 aquaplanet_waccm_2000 2010_cam6 diff --git a/cime_config/config_compsets.xml b/cime_config/config_compsets.xml index 917df56bc5..b351281e1d 100644 --- a/cime_config/config_compsets.xml +++ b/cime_config/config_compsets.xml @@ -293,7 +293,7 @@ QPC7 - 2000_CAM70_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV + 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV From 93996fa59f3e8b79d6056ca1d5cbc93f76987096 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Thu, 31 Oct 2024 11:19:12 -0400 Subject: [PATCH 30/89] only write drydep INFO messages from masterproc --- src/chemistry/mozart/mo_drydep.F90 | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/chemistry/mozart/mo_drydep.F90 b/src/chemistry/mozart/mo_drydep.F90 index 06b87797c4..12e1d3e0a9 100644 --- a/src/chemistry/mozart/mo_drydep.F90 +++ b/src/chemistry/mozart/mo_drydep.F90 @@ -520,11 +520,13 @@ subroutine get_landuse_and_soilw_from_file() logical :: lexist if (len_trim(drydep_srf_file) == 0) then - write(iulog,*)'**************************************' - write(iulog,*)' get_landuse_and_soilw_from_file: INFO:' - write(iulog,*)' drydep_srf_file not set:' - write(iulog,*)' setting fraction_landuse to zero' - write(iulog,*)'**************************************' + if (masterproc) then + write(iulog,*)'**************************************' + write(iulog,*)' get_landuse_and_soilw_from_file: INFO:' + write(iulog,*)' drydep_srf_file not set:' + write(iulog,*)' setting fraction_landuse to zero' + write(iulog,*)'**************************************' + end if fraction_landuse = 0._r8 return end if @@ -536,12 +538,14 @@ subroutine get_landuse_and_soilw_from_file() call infld('fraction_landuse', piofile, 'ncol','class',1,pcols,1,n_land_type, begchunk,endchunk, & fraction_landuse, readvar, gridname='physgrid') if (.not. readvar) then - write(iulog,*)'**************************************' - write(iulog,*)'get_landuse_and_soilw_from_file: INFO:' - write(iulog,*)' fraction_landuse not read from file: ' - write(iulog,*)' ', trim(locfn) - write(iulog,*)' setting all values to zero' - write(iulog,*)'**************************************' + if (masterproc) then + write(iulog,*)'**************************************' + write(iulog,*)'get_landuse_and_soilw_from_file: INFO:' + write(iulog,*)' fraction_landuse not read from file: ' + write(iulog,*)' ', trim(locfn) + write(iulog,*)' setting all values to zero' + write(iulog,*)'**************************************' + end if fraction_landuse = 0._r8 end if From fe03fe49dd1bac237b32abfa09b74c44aa65a566 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Wed, 6 Nov 2024 10:32:26 -0500 Subject: [PATCH 31/89] only do modal aerosol calcs when modal aerosols are used --- src/physics/cam7/physpkg.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 83d03c46d1..91dc3311df 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -2882,8 +2882,10 @@ subroutine tphysbc (ztodt, state, & ! Run wet deposition routines to intialize aerosols !=================================================== - call modal_aero_calcsize_diag(state, pbuf) - call modal_aero_wateruptake_dr(state, pbuf) + if (clim_modal_aero) then + call modal_aero_calcsize_diag(state, pbuf) + call modal_aero_wateruptake_dr(state, pbuf) + end if !=================================================== ! Radiation computations From cdafa1a19e74d70ba27c4862fc13f39abe7feef4 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 8 Nov 2024 10:09:00 -0500 Subject: [PATCH 32/89] updates to QPC7 --- .../use_cases/aquaplanet_cam7.xml | 8 ++++ cime_config/config_component.xml | 1 + doc/ChangeLog | 41 +++++++++++++++++-- src/physics/cam/nucleate_ice_cam.F90 | 18 +++++--- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/bld/namelist_files/use_cases/aquaplanet_cam7.xml b/bld/namelist_files/use_cases/aquaplanet_cam7.xml index a7be0ebf7b..d6766e2ff3 100644 --- a/bld/namelist_files/use_cases/aquaplanet_cam7.xml +++ b/bld/namelist_files/use_cases/aquaplanet_cam7.xml @@ -16,6 +16,8 @@ 1.650e-6 0.306e-6 348.0e-6 +0.0 +0.0 atm/cam/solar/ape_solar_ave_tsi_1365.nc @@ -42,7 +44,13 @@ "" "" "" + "" + "" 0.0 + + 'A:Q:H2O', 'N:O2:O2', 'N:CO2:CO2', 'N:ozone:O3', + 'N:N2O:N2O', 'N:CH4:CH4', 'N:CFC11:CFC11', 'N:CFC12:CFC12' + diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 0b39ec4b08..17bb9cf5a9 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -204,6 +204,7 @@ -aquaplanet -aquaplanet + -chem none -offline_drv rad diff --git a/doc/ChangeLog b/doc/ChangeLog index bdb7b78674..28260c5ddf 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -3,23 +3,25 @@ Tag name: Originator(s): eaton Date: -One-line Summary: fix issues #1159, #670 +One-line Summary: Add QPC7 compset, plus misc. Github PR URL: Purpose of changes (include the issue number and title text for each relevant GitHub issue): +Issue #814 - Introduce QPC7 and possibly QPS7 aquaplanet compsets + - Create QPC7 compset. Open new issue to address QPS7. + Issue #1159 - Prealpha tests exceeding wallclock - increased time limit to 20 minutes for these prealpha tests: ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s Issue #670 - DAE test broken - . ChangeLog indicates that this test has never worked since it was added + - ChangeLog indicates that this test has never worked since it was added in cam6_2_046 (2020-09-01). Test removed. - Describe any changes made to build system: Describe any changes made to the namelist: @@ -42,12 +44,45 @@ List all files added and what they do: List all existing files that have been modified, and describe the changes: +bld/namelist_files/use_cases/aquaplanet_cam7.xml +. use case file for QPC7. Same as for QPC6 except: + - set f11vmr=f12vmr=0. Otherwise defaults from namelist_defaults_cam.xml + are used. + - set prescribed_aero_file="" and prescribed_aero_specifier="". + By default build-namelist will provide a bulk aerosol specification. + - set rad_climate to just make the GHGs radiatively active. + By default build-namelist will add bulk aerosols. + +cime_config/config_component.xml +. CAM_CONFIG_OPTS + - add match for _CAM70.*_SLND_SICE_DOCN%AQP to set '-chem none' +. CAM_NML_USE_CASE + - add match for 2000_CAM70.*_SLND_SICE_DOCN%AQP to use aquaplanet_cam7. + This match will work for both %LT and %MT configs. + +cime_config/config_compsets.xml +. QPC7 = 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV + cime_config/testdefs/testlist_cam.xml . increase time limit to 20 minutes for these prealpha tests: ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s . remove non-working DAE test +src/chemistry/mozart/mo_drydep.F90 +. get_landuse_and_soilw_from_file + - restrict the INFO messages to only print from masterproc + +src/physics/cam/nucleate_ice_cam.F90 +. nucleate_ice_cam_calc + - add conditionals so naer2 array not referenced when there are no + aerosols. + +src/physics/cam7/physpkg.F90 +. tphysbc + - add conditionals so modal aerosol calculations only called when modal + aerosols are present. + If there were any failures reported from running test_driver.sh on any test platform, and checkin with these failures has been OK'd by the gatekeeper, then copy the lines from the td.*.status files for the failed tests to the diff --git a/src/physics/cam/nucleate_ice_cam.F90 b/src/physics/cam/nucleate_ice_cam.F90 index 7dff84f529..a247128c40 100644 --- a/src/physics/cam/nucleate_ice_cam.F90 +++ b/src/physics/cam/nucleate_ice_cam.F90 @@ -607,12 +607,18 @@ subroutine nucleate_ice_cam_calc( & else ! for bulk model - dust_num_col(:ncol,:) = naer2(:ncol,:,idxdst1)/25._r8 * per_cm3 & ! #/cm3 - + naer2(:ncol,:,idxdst2)/25._r8 * per_cm3 & - + naer2(:ncol,:,idxdst3)/25._r8 * per_cm3 & - + naer2(:ncol,:,idxdst4)/25._r8 * per_cm3 - sulf_num_col(:ncol,:) = naer2(:ncol,:,idxsul)/25._r8 * per_cm3 - soot_num_col(:ncol,:) = naer2(:ncol,:,idxbcphi)/25._r8 * per_cm3 + if (idxdst1 > 0 .and. idxdst2 > 0 .and. idxdst3 > 0 .and. idxdst4 > 0) then + dust_num_col(:ncol,:) = naer2(:ncol,:,idxdst1)/25._r8 * per_cm3 & ! #/cm3 + + naer2(:ncol,:,idxdst2)/25._r8 * per_cm3 & + + naer2(:ncol,:,idxdst3)/25._r8 * per_cm3 & + + naer2(:ncol,:,idxdst4)/25._r8 * per_cm3 + end if + if (idxsul > 0) then + sulf_num_col(:ncol,:) = naer2(:ncol,:,idxsul)/25._r8 * per_cm3 + end if + if (idxbcphi > 0) then + soot_num_col(:ncol,:) = naer2(:ncol,:,idxbcphi)/25._r8 * per_cm3 + end if endif kloop: do k = top_lev, pver From b1a243ce649a5061d6f7d3c8b1d54092fc02f924 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Mon, 11 Nov 2024 16:18:28 -0700 Subject: [PATCH 33/89] Adding timer around all code in the do_rainturb option rather than just the function call. --- src/physics/cam/clubb_intr.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 6fa4fa2936..585dd328d6 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3817,6 +3817,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if if ( do_rainturb ) then + call t_startf('clubb_tend_cam:do_rainturb') do k=1,nzm_clubb do i=1,ncol @@ -3824,14 +3825,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - call t_startf('clubb_tend_cam:update_xp2_mc_api') call update_xp2_mc_api( gr, nzm_clubb, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & rtp2_mc_out, thlp2_mc_out, & wprtp_mc_out, wpthlp_mc_out, & rtpthlp_mc_out) - call t_stopf('clubb_tend_cam:update_xp2_mc_api') do k=1,nzm_clubb do i=1,ncol @@ -3845,6 +3844,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + call t_stopf('clubb_tend_cam:do_rainturb') end if if (do_cldcool) then From 7244285a9702f8ec99478bc5dc9d6991a634826a Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 18 Nov 2024 11:26:46 -0500 Subject: [PATCH 34/89] Update build issues; atmos_phys external to head of PR --- .gitmodules | 2 +- src/atmos_phys | 2 +- src/physics/cam/check_energy.F90 | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 195d003bc2..c478c0c686 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/jimmielin/atmospheric_physics - fxtag = 7b188e35 + fxtag = b1e2c2a9 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index 7b188e35fe..b1e2c2a9d1 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 7b188e35fe26247289d3bdbbbdd902cde382765a +Subproject commit b1e2c2a9d188172f888b0b5c903c5a12a741f30e diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 774764c563..9fbc2d592c 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -814,6 +814,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & ncol = ncol, & pver = pver, & pcnst = pcnst, & + iulog = iulog, & q = state%q(1:ncol,1:pver,1:pcnst), & pdel = state%pdel(1:ncol,1:pver), & u = state%u(1:ncol,1:pver), & @@ -852,7 +853,7 @@ end subroutine check_energy_cam_chng ! Add heating rate required for global mean total energy conservation subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) use physics_types, only: physics_ptend, physics_ptend_init - use physconst, only: rga + use physconst, only: gravit ! SCAM support use scamMod, only: single_column, use_camiop, heat_glob_scm @@ -902,7 +903,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) ncol = ncol, & pver = pver, & pint = state%pint(:ncol,:), & - rga = rga, & + gravit = gravit, & heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & eshflx = eshflx(:ncol) & From e3e6a131208feaf72360d5fa5767ddf638ecc3c9 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 18 Nov 2024 11:52:16 -0500 Subject: [PATCH 35/89] Update check_energy_cam_fix interface --- src/physics/cam/check_energy.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9fbc2d592c..592faeab00 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -872,6 +872,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) integer :: ncol ! number of atmospheric columns in chunk integer :: lchnk ! chunk number real(r8) :: heat_out(pcols) + character(len=64) :: dummy_scheme_name ! dumy scheme name for CCPP-ized scheme lchnk = state%lchnk ncol = state%ncol @@ -906,7 +907,8 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) gravit = gravit, & heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & - eshflx = eshflx(:ncol) & + eshflx = eshflx(:ncol), & + scheme_name = dummy_scheme_name ) end subroutine check_energy_cam_fix From a10a9557acc06679839e64682c9c3f5f4b96663b Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 18 Nov 2024 13:15:13 -0500 Subject: [PATCH 36/89] Update check_energy_cam_fix interface (2) --- src/physics/cam/check_energy.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 592faeab00..3f203bae2c 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -872,7 +872,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) integer :: ncol ! number of atmospheric columns in chunk integer :: lchnk ! chunk number real(r8) :: heat_out(pcols) - character(len=64) :: dummy_scheme_name ! dumy scheme name for CCPP-ized scheme + character(len=64) :: dummy_scheme_name ! dummy scheme name for CCPP-ized scheme lchnk = state%lchnk ncol = state%ncol @@ -908,7 +908,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & eshflx = eshflx(:ncol), & - scheme_name = dummy_scheme_name + scheme_name = dummy_scheme_name & ) end subroutine check_energy_cam_fix From 902c495ebb7ec85b107ed7cba8bf003136b9ca04 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 19 Nov 2024 12:26:51 -0500 Subject: [PATCH 37/89] Update atmos_phys to atmos_phys0_07_000 --- .gitmodules | 4 ++-- src/atmos_phys | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index c478c0c686..40e189dab5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,8 +35,8 @@ [submodule "atmos_phys"] path = src/atmos_phys - url = https://github.com/jimmielin/atmospheric_physics - fxtag = b1e2c2a9 + url = https://github.com/ESCOMP/atmospheric_physics + fxtag = atmos_phys0_07_000 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index b1e2c2a9d1..e10f81151e 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit b1e2c2a9d188172f888b0b5c903c5a12a741f30e +Subproject commit e10f81151ecef5416462472ef0e52810dc82e412 From 7aeabafad18b1f729792eaad61e865c84acf6df6 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Wed, 20 Nov 2024 17:00:17 -0500 Subject: [PATCH 38/89] change QPC7 to QPLT; add QPMT --- cime_config/config_compsets.xml | 7 ++++++- doc/ChangeLog | 22 ++++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cime_config/config_compsets.xml b/cime_config/config_compsets.xml index b351281e1d..31eba44982 100644 --- a/cime_config/config_compsets.xml +++ b/cime_config/config_compsets.xml @@ -292,10 +292,15 @@ - QPC7 + QPLT 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV + + QPMT + 2000_CAM70%MT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV + + QPC2000climo 2000_CAM60%CT1S_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV diff --git a/doc/ChangeLog b/doc/ChangeLog index 004d034792..b385aca2a2 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -3,13 +3,14 @@ Tag name: Originator(s): eaton Date: -One-line Summary: Add QPC7 compset, plus misc. +One-line Summary: Add QPLT and QPMT compsets, plus misc. Github PR URL: Purpose of changes (include the issue number and title text for each relevant GitHub issue): Issue #814 - Introduce QPC7 and possibly QPS7 aquaplanet compsets - - Create QPC7 compset. Open new issue to address QPS7. + - Analogous to compset names with FLT and FMT, create QPLT and QPMT compsets. + - Open new issue to address QPS7. Issue #1159 - Prealpha tests exceeding wallclock - increased time limit to 20 minutes for these prealpha tests: @@ -45,13 +46,13 @@ List all files added and what they do: List all existing files that have been modified, and describe the changes: bld/namelist_files/use_cases/aquaplanet_cam7.xml -. use case file for QPC7. Same as for QPC6 except: - - set f11vmr=f12vmr=0. Otherwise defaults from namelist_defaults_cam.xml - are used. - - set prescribed_aero_file="" and prescribed_aero_specifier="". - By default build-namelist will provide a bulk aerosol specification. - - set rad_climate to just make the GHGs radiatively active. - By default build-namelist will add bulk aerosols. +. use case file for QPLT and QPMT. Same as for QPC6 except: + - set f11vmr=f12vmr=0 to override the non-zero default values from + namelist_defaults_cam.xml. + - set prescribed_aero_file="" and prescribed_aero_specifier="" to + override the default bulk aerosol settings from build-namelist. + - set rad_climate to just make the GHGs radiatively active to override + the default build-namelist setting which includes bulk aerosols. cime_config/config_component.xml . CAM_CONFIG_OPTS @@ -61,7 +62,8 @@ cime_config/config_component.xml This match will work for both %LT and %MT configs. cime_config/config_compsets.xml -. QPC7 = 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV +. add QPLT = 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV +. add QPMT = 2000_CAM70%MT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV cime_config/testdefs/testlist_cam.xml . increase time limit to 20 minutes for these prealpha tests: From bc5428f4eaaf55641176b61034a1a71363a943cd Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Wed, 20 Nov 2024 21:41:42 -0500 Subject: [PATCH 39/89] Address review comments --- src/control/cam_snapshot_common.F90 | 2 ++ src/physics/cam/check_energy.F90 | 15 +++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/control/cam_snapshot_common.F90 b/src/control/cam_snapshot_common.F90 index fa558b3ad2..0f49d27a02 100644 --- a/src/control/cam_snapshot_common.F90 +++ b/src/control/cam_snapshot_common.F90 @@ -848,6 +848,8 @@ subroutine state_snapshot_all_outfld(lchnk, file_num, state) call outfld(state_snapshot(i)%standard_name, state%te_cur(:, dyn_te_idx), pcols, lchnk) case ('air_composition_cp_or_cv_dycore') + ! this field is not part of physics state (it is in air_composition) + ! but describes the atmospheric thermodynamic state and thus saved within the snapshot call outfld(state_snapshot(i)%standard_name, cp_or_cv_dycore(:,:,lchnk), pcols, lchnk) case default diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 3f203bae2c..5350371cef 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -461,6 +461,9 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) lchnk = state%lchnk ncol = state%ncol + ! The "vertical coordinate" parameter is equivalent to the dynamical core + ! energy formula parameter, which controls the dycore energy formula used + ! by get_hydrostatic_energy. if (present(vc)) then vc_loc = vc else @@ -758,11 +761,11 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & type(physics_tend ), intent(inout) :: tend character*(*),intent(in) :: name ! parameterization name for fluxes integer , intent(in) :: nstep ! current timestep number - real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) - real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) - real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) - real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) - real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) + real(r8), intent(in) :: ztodt ! physics timestep (s) + real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) + real(r8), intent(in) :: flx_cnd(:) ! (pcols) - boundary flux of lwe liquid+ice (m/s) + real(r8), intent(in) :: flx_ice(:) ! (pcols) - boundary flux of lwe ice (m/s) + real(r8), intent(in) :: flx_sen(:) ! (pcols) - boundary flux of sensible heat (W/m2) integer :: lchnk ! chunk identifier integer :: ncol ! number of atmospheric columns @@ -785,7 +788,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling endif - elseif(state%psetcols > pcols) then + else if(state%psetcols > pcols) then ! Subcolumns if(.not. all(cpairv(:,:,:) == cpair)) then call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') From c0b9d8bc47d2a7b658d1b45a31e723f5ca7055a3 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Thu, 21 Nov 2024 08:51:05 -0500 Subject: [PATCH 40/89] Update comment for tot_energy_phys vc parameter --- src/physics/cam/check_energy.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 5350371cef..7af3a32bda 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -425,7 +425,7 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) type(physics_state), intent(inout) :: state character(len=*), intent(in) :: outfld_name_suffix ! suffix for "outfld" - integer, optional, intent(in) :: vc ! vertical coordinate + integer, optional, intent(in) :: vc ! vertical coordinate (controls energy formula to use) !---------------------------Local storage------------------------------- real(r8) :: se(pcols) ! Dry Static energy (J/m2) From 69f53c02a3ce9823a23d8799e2a5b7501b0ac58b Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Wed, 27 Nov 2024 13:50:14 -0500 Subject: [PATCH 41/89] updates for QPLT --- bld/namelist_files/namelist_defaults_cam.xml | 3 ++- cime_config/testdefs/testlist_cam.xml | 1 - doc/ChangeLog | 22 ++++++++++++++------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 462570da4a..4b9722d66d 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -264,11 +264,12 @@ atm/cam/inic/se/ape_cam5_ne120np4_L30_c170419.nc atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L32_01-01-31_c221214.nc -atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L58_01-01-31_c221214.nc +atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L93_01_02_01_c240518.nc atm/cam/inic/se/ape_cam6_ne5np4_L32_c170517.nc atm/cam/inic/se/ape_cam6_ne16np4_L32_c170509.nc atm/cam/inic/se/ape_cam6_ne30np4_L32_c170509.nc +atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc atm/cam/inic/se/ape_cam6_ne120np4_L32_c170908.nc atm/cam/inic/se/ape_cam6_ne240np4_L32_c170908.nc diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index e161286ea8..bce9b11597 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -161,7 +161,6 @@ - diff --git a/doc/ChangeLog b/doc/ChangeLog index b385aca2a2..a02e75661c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -9,8 +9,12 @@ Github PR URL: Purpose of changes (include the issue number and title text for each relevant GitHub issue): Issue #814 - Introduce QPC7 and possibly QPS7 aquaplanet compsets - - Analogous to compset names with FLT and FMT, create QPLT and QPMT compsets. + - Analogous to FLT and FMT compset names, create QPLT and QPMT compsets. - Open new issue to address QPS7. + - The new aquaplanet configurations use '-chem none' to eliminate the + aerosols. This is much faster and requires much less memory than a + configuration that leaves the default chemistry in place and removes + aerosols by zeroing the initial concentrations and emission sources. Issue #1159 - Prealpha tests exceeding wallclock - increased time limit to 20 minutes for these prealpha tests: @@ -21,15 +25,14 @@ Issue #670 - DAE test broken - ChangeLog indicates that this test has never worked since it was added in cam6_2_046 (2020-09-01). Test removed. - - -Describe any changes made to build system: +Describe any changes made to build system: none Describe any changes made to the namelist: +. add spun up initial files for QPLT compset on ne3pg3 and ne30pg3 grids. -List any changes to the defaults for the boundary datasets: +List any changes to the defaults for the boundary datasets: none -Describe any substantial timing or memory changes: +Describe any substantial timing or memory changes: n/a Code reviewed by: @@ -45,6 +48,13 @@ List all files added and what they do: List all existing files that have been modified, and describe the changes: +bld/namelist_files/namelist_defaults_cam.xml +. replace current entry for ne3np4 L58 aquaplanet with + QPLT_L58_ne3pg3_c241127.nc. Also remove the ic_ymd attribute since + aquaplanet does not have an annual cycle and that attribute interferes + with starting a run from an arbitrary time. +. add new file for ne30np4 L58 aquaplanet. + bld/namelist_files/use_cases/aquaplanet_cam7.xml . use case file for QPLT and QPMT. Same as for QPC6 except: - set f11vmr=f12vmr=0 to override the non-zero default values from From 453eea9fbbdef81faa133d53afad3e0bfa895d73 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 29 Nov 2024 10:29:38 -0500 Subject: [PATCH 42/89] add regression tests for QPLT --- cime_config/testdefs/testlist_cam.xml | 13 +++++++++++-- doc/ChangeLog | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index bce9b11597..f4b76a14a0 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -190,13 +190,22 @@ - + - + + + + + + + + + + diff --git a/doc/ChangeLog b/doc/ChangeLog index a02e75661c..0b5e219e2f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -44,7 +44,7 @@ cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl test/system/da_cam_no_data_mod.sh . DAE test removed -List all files added and what they do: +List all files added and what they do: none List all existing files that have been modified, and describe the changes: @@ -80,6 +80,10 @@ cime_config/testdefs/testlist_cam.xml ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s . remove non-working DAE test +. replace ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s + by ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp +. replace ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp + by ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s src/chemistry/mozart/mo_drydep.F90 . get_landuse_and_soilw_from_file From 6330f1a3f2b0b6e3251c1b0d5fe68757a2a10d91 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 29 Nov 2024 14:23:09 -0500 Subject: [PATCH 43/89] fixes for QPLT tests --- bld/namelist_files/namelist_defaults_cam.xml | 4 ++-- bld/namelist_files/use_cases/aquaplanet_cam7.xml | 10 +++++++--- doc/ChangeLog | 12 +++++++++--- src/physics/cam/microp_aero.F90 | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 4b9722d66d..3d1643c4c8 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -264,12 +264,12 @@ atm/cam/inic/se/ape_cam5_ne120np4_L30_c170419.nc atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L32_01-01-31_c221214.nc -atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc +atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L93_01_02_01_c240518.nc atm/cam/inic/se/ape_cam6_ne5np4_L32_c170517.nc atm/cam/inic/se/ape_cam6_ne16np4_L32_c170509.nc atm/cam/inic/se/ape_cam6_ne30np4_L32_c170509.nc -atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc +atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc atm/cam/inic/se/ape_cam6_ne120np4_L32_c170908.nc atm/cam/inic/se/ape_cam6_ne240np4_L32_c170908.nc diff --git a/bld/namelist_files/use_cases/aquaplanet_cam7.xml b/bld/namelist_files/use_cases/aquaplanet_cam7.xml index d6766e2ff3..405e14bbe0 100644 --- a/bld/namelist_files/use_cases/aquaplanet_cam7.xml +++ b/bld/namelist_files/use_cases/aquaplanet_cam7.xml @@ -1,8 +1,11 @@ - - + + +atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc +atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc + 0. 0. @@ -49,7 +52,8 @@ 0.0 - + 'A:Q:H2O', 'N:O2:O2', 'N:CO2:CO2', 'N:ozone:O3', 'N:N2O:N2O', 'N:CH4:CH4', 'N:CFC11:CFC11', 'N:CFC12:CFC12' diff --git a/doc/ChangeLog b/doc/ChangeLog index 6bb0bcedf7..0bd04f1a5e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -50,9 +50,7 @@ List all existing files that have been modified, and describe the changes: bld/namelist_files/namelist_defaults_cam.xml . replace current entry for ne3np4 L58 aquaplanet with - QPLT_L58_ne3pg3_c241127.nc. Also remove the ic_ymd attribute since - aquaplanet does not have an annual cycle and that attribute interferes - with starting a run from an arbitrary time. + QPLT_L58_ne3pg3_c241127.nc. . add new file for ne30np4 L58 aquaplanet. bld/namelist_files/use_cases/aquaplanet_cam7.xml @@ -63,6 +61,9 @@ bld/namelist_files/use_cases/aquaplanet_cam7.xml override the default bulk aerosol settings from build-namelist. - set rad_climate to just make the GHGs radiatively active to override the default build-namelist setting which includes bulk aerosols. + - Add spun-up IC files. This allows us to remove the ic_ymd attribute + which should not be needed for aquaplanet runs. Removing ic_ymd + enables testing with arbitrary start dates. cime_config/config_component.xml . CAM_CONFIG_OPTS @@ -89,6 +90,11 @@ src/chemistry/mozart/mo_drydep.F90 . get_landuse_and_soilw_from_file - restrict the INFO messages to only print from masterproc +src/physics/cam/microp_aero.F90 +. microp_aero_run + - add condition that number of bulk aerosols must be > 0 before calling + ndrop_bam_run. + src/physics/cam/nucleate_ice_cam.F90 . nucleate_ice_cam_calc - add conditionals so naer2 array not referenced when there are no diff --git a/src/physics/cam/microp_aero.F90 b/src/physics/cam/microp_aero.F90 index 4961a139a8..acf3287032 100644 --- a/src/physics/cam/microp_aero.F90 +++ b/src/physics/cam/microp_aero.F90 @@ -756,7 +756,7 @@ subroutine microp_aero_run ( & do k = top_lev, pver do i = 1, ncol - if (state1%q(i,k,cldliq_idx) >= qsmall) then + if (naer_all > 0 .and. state1%q(i,k,cldliq_idx) >= qsmall) then ! get droplet activation rate From 554ec1cce37769ee1373dda07bd81f134dc30daf Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Mon, 2 Dec 2024 12:14:12 -0500 Subject: [PATCH 44/89] fixes in outfrq3s_cosp tests --- .../testmods_dirs/cam/outfrq3s_cosp/shell_commands | 3 +-- .../testmods_dirs/cam/outfrq3s_cosp/user_nl_cam | 3 ++- doc/ChangeLog | 12 +++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands index 09a1939ddb..11a171a04e 100644 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands +++ b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands @@ -1,8 +1,7 @@ CAM_CONFIG_OPTS=`./xmlquery CAM_CONFIG_OPTS --value` if [[ $CAM_CONFIG_OPTS != *"-cosp"* ]]; then - ./xmlchange -append CAM_CONFIG_OPTS="-cosp" + ./xmlchange --append CAM_CONFIG_OPTS="-cosp" fi ./xmlchange ROF_NCPL=\$ATM_NCPL ./xmlchange GLC_NCPL=\$ATM_NCPL -./xmlchange CAM_NML_USE_CASE=UNSET ./xmlchange RUN_STARTDATE="19950101" diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam index ddff96685c..a2a8169e6f 100644 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam @@ -2,4 +2,5 @@ mfilt=1,1,1,1,1,1 ndens=1,1,1,1,1,1 nhtfrq=3,3,3,3,3,3 inithist='ENDOFRUN' -fexcl1='CFAD_DBZE94_CS','CLDTOT_CALCS','CLD_CAL_NOTCS','CS_MIXCERT','CS_MIXPOSS','CS_NOPRECIP','CS_PIA','CS_RAINPOSS','CS_RAINPROB' +fexcl1='CFAD_DBZE94_CS','CLDTOT_CALCS','CLD_CAL_NOTCS','CS_MIXCERT','CS_MIXPOSS','CS_NOPRECIP','CS_PIA', + 'CS_RAINPOSS','CS_RAINPROB','CS_SNOWCERT','CS_SNOWPOSS' diff --git a/doc/ChangeLog b/doc/ChangeLog index 0bd04f1a5e..9e152b8e88 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -27,10 +27,10 @@ Issue #670 - DAE test broken Describe any changes made to build system: none -Describe any changes made to the namelist: -. add spun up initial files for QPLT compset on ne3pg3 and ne30pg3 grids. +Describe any changes made to the namelist: none -List any changes to the defaults for the boundary datasets: none +List any changes to the defaults for the boundary datasets: +. add spun up initial files for QPLT compset on ne3pg3 and ne30pg3 grids. Describe any substantial timing or memory changes: n/a @@ -86,6 +86,12 @@ cime_config/testdefs/testlist_cam.xml . replace ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp by ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s +cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands +. remove "./xmlchange CAM_NML_USE_CASE=UNSET" + +cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam +. add CS_SNOWCERT and CS_SNOWPOSS to fexcl1 + src/chemistry/mozart/mo_drydep.F90 . get_landuse_and_soilw_from_file - restrict the INFO messages to only print from masterproc From 99db7405c90e422df5049c5ee8364c43b7071884 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Tue, 3 Dec 2024 14:20:34 -0700 Subject: [PATCH 45/89] Rename AOAMF as AOA1 and output updated MMR in _tend routine M src/physics/cam/aoa_tracers.F90 --- src/physics/cam/aoa_tracers.F90 | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/physics/cam/aoa_tracers.F90 b/src/physics/cam/aoa_tracers.F90 index f0c272b69d..fc656ad618 100644 --- a/src/physics/cam/aoa_tracers.F90 +++ b/src/physics/cam/aoa_tracers.F90 @@ -31,7 +31,7 @@ module aoa_tracers integer, parameter :: ncnst=3 ! number of constituents implemented by this module ! constituent names - character(len=6), parameter :: c_names(ncnst) = (/'AOAMF ', 'HORZ ', 'VERT '/) + character(len=4), parameter :: c_names(ncnst) = (/'AOA1', 'HORZ', 'VERT'/) ! constituent source/sink names character(len=8), parameter :: src_names(ncnst) = (/'AOAMFSRC', 'HORZSRC ', 'VERTSRC '/) @@ -132,12 +132,12 @@ subroutine aoa_tracers_register if (.not. aoa_tracers_flag) return call cnst_add(c_names(1), mwdry, cpair, 0._r8, ixaoa, readiv=aoa_read_from_ic_file, & - longname='mixing ratio LB tracer') + longname='mixing ratio LB tracer', cam_outfld=.false.) call cnst_add(c_names(2), mwdry, cpair, 1._r8, ixht, readiv=aoa_read_from_ic_file, & - longname='horizontal tracer') + longname='horizontal tracer', cam_outfld=.false.) call cnst_add(c_names(3), mwdry, cpair, 0._r8, ixvt, readiv=aoa_read_from_ic_file, & - longname='vertical tracer') + longname='vertical tracer', cam_outfld=.false.) ifirst = ixaoa @@ -324,6 +324,8 @@ subroutine aoa_tracers_timestep_tend(state, ptend, dt) real(r8), parameter :: mmr0 = 1.0e-6_r8 ! initial lower boundary mmr real(r8), parameter :: per_yr = 0.02_r8 ! fractional increase per year + real(r8) :: mmr_out(pcols,pver,ncnst) + !------------------------------------------------------------------ teul = .5_r8*dt/(86400._r8 * treldays) ! 1/2 for the semi-implicit scheme if dt=time step @@ -371,6 +373,15 @@ subroutine aoa_tracers_timestep_tend(state, ptend, dt) call outfld (src_names(2), ptend%q(:,:,ixht), pcols, lchnk) call outfld (src_names(3), ptend%q(:,:,ixvt), pcols, lchnk) + ! output mixing ratios to history + mmr_out(:ncol,:,1) = state%q(:ncol,:,ixaoa) + dt*ptend%q(1:ncol,:,ixaoa) + mmr_out(:ncol,:,2) = state%q(:ncol,:,ixht) + dt*ptend%q(1:ncol,:,ixht) + mmr_out(:ncol,:,3) = state%q(:ncol,:,ixvt) + dt*ptend%q(1:ncol,:,ixvt) + + call outfld (c_names(1), mmr_out(:,:,1), pcols, lchnk) + call outfld (c_names(2), mmr_out(:,:,2), pcols, lchnk) + call outfld (c_names(3), mmr_out(:,:,3), pcols, lchnk) + end subroutine aoa_tracers_timestep_tend !=========================================================================== From 0624476ba64efc98aa54789d9b1bb23d8be831ae Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 4 Dec 2024 10:53:28 -0700 Subject: [PATCH 46/89] changes to use carma4_09 base --- .gitmodules | 2 +- cime_config/config_pes.xml | 16 +- cime_config/testdefs/testlist_cam.xml | 20 +- .../testmods_dirs/cam/carma_dust/user_nl_cam | 1 - .../cam/carma_meteor_impact/user_nl_cam | 1 - .../cam/carma_meteor_smoke/user_nl_cam | 1 - .../cam/carma_mixed_sulfate/user_nl_cam | 1 - .../testmods_dirs/cam/carma_pmc/user_nl_cam | 1 - .../cam/carma_sea_salt/user_nl_cam | 1 - .../cam/carma_sulfate/user_nl_cam | 1 - .../cam/carma_test_growth/user_nl_cam | 1 - .../cam/carma_test_passive/user_nl_cam | 1 - .../cam/carma_test_radiative/user_nl_cam | 1 - .../cam/carma_test_swelling/user_nl_cam | 1 - .../cam/carma_test_tracers/user_nl_cam | 1 - .../cam/carma_test_tracers2/user_nl_cam | 1 - src/physics/cam/carma_flags_mod.F90 | 236 +-- src/physics/cam/carma_intr.F90 | 48 +- src/physics/cam/physpkg.F90 | 4 +- src/physics/cam7/physpkg.F90 | 4 +- src/physics/carma/base | 2 +- src/physics/carma/cam/carma_constants_mod.F90 | 9 +- src/physics/carma/cam/carma_intr.F90 | 1417 +++++++++++------ src/physics/carma/cam/carma_precision_mod.F90 | 2 +- .../carma/models/bc_strat/carma_model_mod.F90 | 2 +- .../carma/models/cirrus/carma_model_mod.F90 | 10 +- src/physics/carma/models/cirrus/growevapl.F90 | 2 +- .../carma/models/cirrus_dust/carma_mod.F90 | 2 +- .../models/cirrus_dust/carma_model_mod.F90 | 14 +- .../carma/models/cirrus_dust/growevapl.F90 | 2 +- .../carma/models/dust/carma_model_mod.F90 | 231 ++- .../meteor_impact/carma_model_flags_mod.F90 | 20 +- .../models/meteor_impact/carma_model_mod.F90 | 275 +++- .../models/meteor_smoke/carma_model_mod.F90 | 237 ++- .../models/mixed_sulfate/carma_model_mod.F90 | 257 ++- .../carma/models/pmc/carma_model_mod.F90 | 263 ++- .../models/pmc_sulfate/carma_model_mod.F90 | 10 +- .../carma/models/sea_salt/carma_model_mod.F90 | 235 ++- .../carma/models/sulfate/carma_model_mod.F90 | 192 ++- .../models/test_detrain/carma_model_mod.F90 | 2 +- .../models/test_growth/carma_model_mod.F90 | 235 ++- .../models/test_passive/carma_model_mod.F90 | 196 ++- .../models/test_radiative/carma_model_mod.F90 | 203 ++- .../models/test_swelling/carma_model_mod.F90 | 202 ++- .../models/test_tracers/carma_model_mod.F90 | 215 ++- .../models/test_tracers2/carma_model_mod.F90 | 219 ++- .../carma/models/tholin/carma_model_mod.F90 | 8 +- test/system/TR8.sh | 4 + 48 files changed, 3620 insertions(+), 1189 deletions(-) diff --git a/.gitmodules b/.gitmodules index 817bb1ff6b..9e0fa05361 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,7 +9,7 @@ path = src/physics/carma/base url = https://github.com/ESCOMP/CARMA_base.git fxrequired = AlwaysRequired - fxtag = carma4_01 + fxtag = carma4_09 fxDONOTUSEurl = https://github.com/ESCOMP/CARMA_base.git [submodule "pumas"] diff --git a/cime_config/config_pes.xml b/cime_config/config_pes.xml index f488c21b27..47bbcc4af3 100644 --- a/cime_config/config_pes.xml +++ b/cime_config/config_pes.xml @@ -1678,14 +1678,14 @@ none - 36 - 36 - 36 - 36 - 36 - 36 - 36 - 36 + 32 + 32 + 32 + 32 + 32 + 32 + 32 + 32 1 diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index c95f004d25..2801e231f7 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -582,6 +582,7 @@ + @@ -602,6 +603,7 @@ + @@ -625,6 +627,7 @@ + @@ -636,6 +639,7 @@ + @@ -691,6 +695,7 @@ + @@ -767,18 +772,10 @@ - - - - - - - - - + @@ -799,6 +796,7 @@ + @@ -809,6 +807,7 @@ + @@ -829,6 +828,7 @@ + @@ -839,6 +839,7 @@ + @@ -859,6 +860,7 @@ + diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam index cfac3a4818..9893ae9a9e 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam @@ -6,4 +6,3 @@ pbuf_global_allocate=.false. history_carma=.true. fincl2 = 'CRSLERFC' carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam index 36487d1f35..ca4ea707ef 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" solar_data_type='FIXED' solar_data_ymd=20000101 carma_emis_maxlat = 40. diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam index f69245ce24..2a81a976e2 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" solar_data_type='FIXED' solar_data_ymd=20000101 diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam index 52b192f861..d292329b4c 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" flbc_list = 'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2', 'HCFC22', 'N2O', 'OCS' solar_data_type='FIXED' diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam index b40ad17f97..3ec29d7308 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam @@ -6,4 +6,3 @@ pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. carma_do_partialinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam index cfc4580f54..e3a93951a0 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" flbc_list = 'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2', 'HCFC22', 'N2O', 'OCS' solar_data_type='FIXED' diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/src/physics/cam/carma_flags_mod.F90 b/src/physics/cam/carma_flags_mod.F90 index 59fee48bf3..e583b43d90 100644 --- a/src/physics/cam/carma_flags_mod.F90 +++ b/src/physics/cam/carma_flags_mod.F90 @@ -11,8 +11,13 @@ module carma_flags_mod use spmd_utils, only: masterproc ! Flags for integration with CAM Microphysics - public carma_readnl ! read the carma namelist - + + implicit none + public + + integer, parameter :: carma_maxdiags = 100 + integer, protected :: carma_ndiagpkgs ! Number of diags_packages listed + integer, protected :: carma_ndebugpkgs ! Number of diags_packages listed ! Namelist flags ! @@ -20,45 +25,53 @@ module carma_flags_mod ! calculations, but it will still initialize itself. This allows the same build and ! namelist to be used, but the CARMA processing diabled. Use the configure option ! -carma none to totally disable CARMA and prevent even the register from happening. - logical, public :: carma_flag = .false. ! If .true. then turn on CARMA microphysics in CAM - logical, public :: carma_do_aerosol = .true. ! If .true. then CARMA is processed after surface coupling - logical, public :: carma_do_cldice = .false. ! If .true. then do cloud ice - logical, public :: carma_do_cldliq = .false. ! If .true. then do cloud liquid - logical, public :: carma_do_clearsky = .false. ! If .true. then do clear sky particle calculations - logical, public :: carma_do_coag = .false. ! If .true. then do coagulation - logical, public :: carma_do_detrain = .false. ! If .true. then do detrain - logical, public :: carma_do_drydep = .false. ! If .true. then do dry deposition - logical, public :: carma_do_emission = .false. ! If .true. then do emission - logical, public :: carma_do_fixedinit= .false. ! If .true. then do fixed initialization to a reference state - logical, public :: carma_hetchem_feedback= .false.! If .true. then CARMA sulfate surface area density used in heterogeneous chemistry - logical, public :: carma_rad_feedback= .false. ! If .true. then CARMA sulfate mass mixing ratio & effective radius used in radiation - logical, public :: carma_do_explised = .false. ! If .true. then do sedimentation with substepping - logical, public :: carma_do_incloud = .false. ! If .true. then do incloud particle calculations - logical, public :: carma_do_grow = .false. ! If .true. then do growth - logical, public :: carma_do_optics = .false. ! If .true. then do optical properties file - logical, public :: carma_do_partialinit= .false. ! If .true. then do initialization of coagulation to a reference state (requires fixedinit) - logical, public :: carma_do_pheat = .false. ! If .true. then do particle heating - logical, public :: carma_do_pheatatm = .false. ! If .true. then do particle heating of atmosphere - logical, public :: carma_do_substep = .false. ! If .true. then do substeping - logical, public :: carma_do_thermo = .false. ! If .true. then do solve thermodynamics equation - logical, public :: carma_do_wetdep = .false. ! If .true. then do wet deposition - logical, public :: carma_do_vdiff = .false. ! If .true. then do vertical brownian diffusion - logical, public :: carma_do_vtran = .false. ! If .true. then do vertical transport - integer, public :: carma_maxsubsteps = 1 ! Maximum number of time substeps allowed - integer, public :: carma_minsubsteps = 1 ! Minimum number of time substeps allowed - integer, public :: carma_maxretries = 8 ! Maximum number of time substeps allowed - real(r8), public :: carma_conmax = 0.1_r8 ! Minumum relative concentration to consider in substep - real(r8), public :: carma_dgc_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas concentration allowed per substep. - real(r8), public :: carma_ds_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas saturation allowed per substep. - real(r8), public :: carma_dt_threshold = 0.0_r8 ! When non-zero, the largest change in temperature (K) allowed per substep. - real(r8), public :: carma_tstick = 1.0_r8 ! Thermal accommodation coefficient - real(r8), public :: carma_gsticki = 0.93_r8 ! Growth accommodation coefficient for ice - real(r8), public :: carma_gstickl = 1.0_r8 ! Growth accommodation coefficient for liquid - real(r8), public :: carma_cstick = 1.0_r8 ! Coagulation accommodation coefficient - real(r8), public :: carma_rhcrit = 1.0_r8 ! Critical relative humidity for liquid clouds - real(r8), public :: carma_vf_const = 0.0_r8 ! If specified and non-zero, constant fall velocity for all particles [cm/s] - character(len=256), public :: carma_reftfile = 'carma_reft.nc' ! path to the file containing the reference temperature profile - character(len=32), public :: carma_model = "none" ! String (no spaces) that identifies the model + logical, protected :: carma_flag = .false. ! If .true. then turn on CARMA microphysics in CAM + logical, protected :: carma_do_aerosol = .true. ! If .true. then CARMA is processed after surface coupling + logical, protected :: carma_do_coremasscheck = .false. ! If .true. then do coremasscheck and abort model after certain subroutines + logical, protected :: carma_do_cldice = .false. ! If .true. then do cloud ice + logical, protected :: carma_do_cldliq = .false. ! If .true. then do cloud liquid + logical, protected :: carma_do_clearsky = .false. ! If .true. then do clear sky particle calculations + logical, protected :: carma_do_cloudborne = .false. ! If .true. then do then the carma groups can be cloudborne + logical, protected :: carma_do_coag = .false. ! If .true. then do coagulation + logical, protected :: carma_do_detrain = .false. ! If .true. then do detrain + logical, protected :: carma_do_drydep = .false. ! If .true. then do dry deposition + logical, protected :: carma_do_emission = .false. ! If .true. then do emission + logical, protected :: carma_do_fixedinit= .false. ! If .true. then do fixed initialization to a reference state + logical, protected :: carma_hetchem_feedback=.false.! If .true. then CARMA sulfate surface area density used in heterogeneous chemistry + logical, protected :: carma_rad_feedback= .false. ! If .true. then CARMA sulfate mass mixing ratio & effective radius used in radiation + logical, protected :: carma_do_explised = .false. ! If .true. then do sedimentation with substepping + logical, protected :: carma_do_incloud = .false. ! If .true. then do incloud particle calculations + logical, protected :: carma_do_budget_diags = .false. ! If .true. then do budget diagnostics + logical, protected :: carma_do_package_diags = .false. ! If .true. then do package diagnostics + logical, protected :: carma_do_grow = .false. ! If .true. then do growth + logical, protected :: carma_do_optics = .false. ! If .true. then do optical properties file + logical, protected :: carma_do_partialinit= .false. ! If .true. then do initialization of coagulation to a reference state (requires fixedinit) + logical, protected :: carma_do_pheat = .false. ! If .true. then do particle heating + logical, protected :: carma_do_pheatatm = .false. ! If .true. then do particle heating of atmosphere + logical, protected :: carma_do_substep = .false. ! If .true. then do substeping + logical, protected :: carma_do_thermo = .false. ! If .true. then do solve thermodynamics equation + logical, protected :: carma_do_wetdep = .false. ! If .true. then do wet deposition + logical, protected :: carma_do_vdiff = .false. ! If .true. then do vertical brownian diffusion + logical, protected :: carma_do_vtran = .false. ! If .true. then do vertical transport + integer, protected :: carma_diags_file = 0 ! Default file for diagnostic output + integer, protected :: carma_maxsubsteps = 1 ! Maximum number of time substeps allowed + integer, protected :: carma_minsubsteps = 1 ! Minimum number of time substeps allowed + integer, protected :: carma_maxretries = 8 ! Maximum number of time substeps allowed + real(r8), protected :: carma_conmax = 0.1_r8 ! Minumum relative concentration to consider in substep + real(r8), protected :: carma_dgc_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas concentration allowed per substep. + real(r8), protected :: carma_ds_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas saturation allowed per substep. + real(r8), protected :: carma_dt_threshold = 0.0_r8 ! When non-zero, the largest change in temperature (K) allowed per substep. + real(r8), protected :: carma_tstick = 1.0_r8 ! Thermal accommodation coefficient + real(r8), protected :: carma_gsticki = 0.93_r8 ! Growth accommodation coefficient for ice + real(r8), protected :: carma_gstickl = 1.0_r8 ! Growth accommodation coefficient for liquid + real(r8), protected :: carma_cstick = 1.0_r8 ! Coagulation accommodation coefficient + real(r8), protected :: carma_rhcrit = 1.0_r8 ! Critical relative humidity for liquid clouds + real(r8), protected :: carma_vf_const = 0.0_r8 ! If specified and non-zero, constant fall velocity for all particles [cm/s] + character(len=32), protected :: carma_model = "none" ! String (no spaces) that identifies the model + character(len=10), protected :: carma_sulfnuc_method = "none" ! Sulfate Nucleation method + character(len=32), protected :: carma_diags_packages(carma_maxdiags) = " " ! Names of physics packages for which diagnostic output is desired + character(len=12), protected :: carma_debug_packages(carma_maxdiags) = " " ! Names of physics packages for which debug output is desired + contains @@ -68,30 +81,31 @@ module carma_flags_mod !! @author Chuck Bardeen !! @version Aug-2010 subroutine carma_readnl(nlfile) - + ! Read carma namelist group. - + use cam_abortutils, only: endrun use namelist_utils, only: find_group_name - use units, only: getunit, freeunit - use mpishorthand + use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character use carma_model_flags_mod, only: carma_model_readnl - + ! args - + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input - + ! local vars - - integer :: unitn, ierr - + + integer :: unitn, ierr, i + ! read namelist for CARMA namelist /carma_nl/ & carma_flag, & carma_do_aerosol, & + carma_do_coremasscheck, & carma_do_cldliq, & carma_do_cldice, & carma_do_clearsky, & + carma_do_cloudborne, & carma_do_coag, & carma_do_detrain, & carma_do_drydep, & @@ -115,7 +129,6 @@ subroutine carma_readnl(nlfile) carma_minsubsteps, & carma_maxretries, & carma_model, & - carma_reftfile, & carma_conmax, & carma_dgc_threshold, & carma_ds_threshold, & @@ -125,11 +138,16 @@ subroutine carma_readnl(nlfile) carma_gstickl, & carma_cstick, & carma_rhcrit, & - carma_vf_const - + carma_vf_const, & + carma_sulfnuc_method, & + carma_do_budget_diags, & + carma_do_package_diags, & + carma_diags_packages, & + carma_debug_packages, & + carma_diags_file + if (masterproc) then - unitn = getunit() - open( unitn, file=trim(nlfile), status='old' ) + open( newunit=unitn, file=trim(nlfile), status='old' ) call find_group_name(unitn, 'carma_nl', status=ierr) if (ierr == 0) then read(unitn, carma_nl, iostat=ierr) @@ -138,54 +156,72 @@ subroutine carma_readnl(nlfile) end if end if close(unitn) - call freeunit(unitn) end if - -#ifdef SPMD - call mpibcast (carma_flag, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_aerosol, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_cldliq, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_cldice, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_clearsky, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_coag, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_detrain, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_drydep, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_emission, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_fixedinit, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_hetchem_feedback,1 ,mpilog, 0,mpicom) - call mpibcast (carma_rad_feedback, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_explised, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_incloud, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_grow, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_optics, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_partialinit, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_pheat, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_pheatatm, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_substep, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_thermo, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_wetdep, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_vdiff, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_vtran, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_maxsubsteps, 1 ,mpiint, 0,mpicom) - call mpibcast (carma_minsubsteps, 1 ,mpiint, 0,mpicom) - call mpibcast (carma_maxretries, 1 ,mpiint, 0,mpicom) - call mpibcast (carma_conmax, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_dgc_threshold, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_ds_threshold, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_dt_threshold, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_tstick, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_gsticki, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_gstickl, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_cstick, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_rhcrit, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_vf_const, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_model, len(carma_model), mpichar, 0, mpicom) - call mpibcast (carma_reftfile, len(carma_reftfile), mpichar, 0, mpicom) -#endif + + call mpi_bcast (carma_flag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_aerosol, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_coremasscheck,1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_cldliq, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_cldice, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_clearsky, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_cloudborne, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_coag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_detrain, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_drydep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_emission, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_fixedinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_hetchem_feedback,1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_rad_feedback, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_explised, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_budget_diags, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_package_diags,1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_incloud, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_grow, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_optics, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_partialinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_pheat, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_pheatatm, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_substep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_thermo, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_wetdep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_vdiff, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_vtran, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_diags_file, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_maxsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_minsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_maxretries, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_conmax, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_dgc_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_ds_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_dt_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_tstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_gsticki, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_gstickl, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_cstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_rhcrit, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_vf_const, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_model, len(carma_model), mpi_character, masterprocid, mpicom, ierr) + call mpi_bcast (carma_sulfnuc_method, len(carma_sulfnuc_method), mpi_character, masterprocid, mpicom, ierr) + call mpibcast (carma_diags_packages, len(carma_diags_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + call mpibcast (carma_debug_packages, len(carma_debug_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + + carma_ndiagpkgs = 0 + do i = 1, carma_maxdiags + if (len_trim(carma_diags_packages(i)) > 0) then + carma_ndiagpkgs = carma_ndiagpkgs + 1 + endif + enddo + + carma_ndebugpkgs = 0 + do i = 1, carma_maxdiags + if (len_trim(carma_debug_packages(i)) > 0) then + carma_ndebugpkgs = carma_ndebugpkgs + 1 + endif + enddo ! Also cause the CARMA model flags to be read in. call carma_model_readnl(nlfile) - + end subroutine carma_readnl end module carma_flags_mod diff --git a/src/physics/cam/carma_intr.F90 b/src/physics/cam/carma_intr.F90 index fc09de5246..b555aaf68a 100644 --- a/src/physics/cam/carma_intr.F90 +++ b/src/physics/cam/carma_intr.F90 @@ -22,12 +22,12 @@ module carma_intr implicit none - + private save ! Public interfaces - + ! CAM Physics Interface public carma_register ! register consituents public carma_is_active ! retrns true if this package is active (microphysics = .true.) @@ -38,11 +38,11 @@ module carma_intr public carma_timestep_init ! initialize timestep dependent variables public carma_timestep_tend ! interface to tendency computation public carma_accumulate_stats ! collect stats from all MPI tasks - + ! Other Microphysics public carma_emission_tend ! calculate tendency from emission source function public carma_wetdep_tend ! calculate tendency from wet deposition - + contains @@ -55,40 +55,41 @@ end subroutine carma_register function carma_is_active() implicit none - + logical :: carma_is_active - + carma_is_active = .false. - + return end function carma_is_active function carma_implements_cnst(name) implicit none - + character(len=*), intent(in) :: name !! constituent name logical :: carma_implements_cnst ! return value carma_implements_cnst = .false. - + return end function carma_implements_cnst - - subroutine carma_init + + subroutine carma_init(pbuf2d) implicit none - + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + return end subroutine carma_init subroutine carma_final implicit none - + return end subroutine carma_final - + subroutine carma_timestep_init implicit none @@ -103,7 +104,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli use time_manager, only: get_nstep, get_step_size, is_first_step use camsrfexch, only: cam_in_t, cam_out_t use scamMod, only: single_column - + implicit none type(physics_state), intent(inout) :: state !! physics state variables @@ -114,13 +115,13 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer real(r8), intent(in), optional :: dlf(pcols,pver) !! Detraining cld H20 from convection (kg/kg/s) real(r8), intent(inout), optional :: rliq(pcols) !! vertical integral of liquid not yet in q(ixcldliq) - real(r8), intent(out), optional :: prec_str(pcols) !! [Total] sfc flux of precip from stratiform (m/s) + real(r8), intent(out), optional :: prec_str(pcols) !! [Total] sfc flux of precip from stratiform (m/s) real(r8), intent(out), optional :: snow_str(pcols) !! [Total] sfc flux of snow from stratiform (m/s) real(r8), intent(out), optional :: prec_sed(pcols) !! total precip from cloud sedimentation (m/s) real(r8), intent(out), optional :: snow_sed(pcols) !! snow from cloud ice sedimentation (m/s) real(r8), intent(in), optional :: ustar(pcols) !! friction velocity (m/s) real(r8), intent(in), optional :: obklen(pcols) !! Obukhov length [ m ] - + call physics_ptend_init(ptend,state%psetcols,'none') !Initialize an empty ptend for use with physics_update if (present(prec_str)) prec_str(:) = 0._r8 @@ -140,27 +141,28 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q) real(r8), intent(in) :: lonvals(:) !! lon in degrees (ncol) logical, intent(in) :: mask(:) !! Only initialize where .true. real(r8), intent(out) :: q(:,:) !! mass mixing ratio - + if (name == "carma") then q = 0._r8 - end if - + end if + return end subroutine carma_init_cnst - subroutine carma_emission_tend(state, ptend, cam_in, dt) + subroutine carma_emission_tend(state, ptend, cam_in, dt, pbuf) use camsrfexch, only: cam_in_t implicit none - + type(physics_state), intent(in ) :: state !! physics state type(physics_ptend), intent(inout) :: ptend !! physics state tendencies type(cam_in_t), intent(inout) :: cam_in !! surface inputs real(r8), intent(in) :: dt !! time step (s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer return - end subroutine carma_emission_tend + end subroutine carma_emission_tend subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index ba36670ce8..a387c0adca 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -855,7 +855,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call aer_rad_props_init() ! initialize carma - call carma_init() + call carma_init(pbuf2d) ! Prognostic chemistry. call chem_init(phys_state,pbuf2d) @@ -1530,7 +1530,7 @@ subroutine tphysac (ztodt, cam_in, & if (carma_do_emission) then ! carma emissions - call carma_emission_tend (state, ptend, cam_in, ztodt) + call carma_emission_tend (state, ptend, cam_in, ztodt, pbuf) call physics_update(state, ptend, ztodt, tend) end if diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 83d03c46d1..57cb9d8d21 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -853,7 +853,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call aer_rad_props_init() ! initialize carma - call carma_init() + call carma_init(pbuf2d) ! Prognostic chemistry. call chem_init(phys_state,pbuf2d) @@ -1615,7 +1615,7 @@ subroutine tphysac (ztodt, cam_in, & if (carma_do_emission) then ! carma emissions - call carma_emission_tend (state, ptend, cam_in, ztodt) + call carma_emission_tend (state, ptend, cam_in, ztodt, pbuf) call physics_update(state, ptend, ztodt, tend) end if diff --git a/src/physics/carma/base b/src/physics/carma/base index bf165cd84e..67418505b4 160000 --- a/src/physics/carma/base +++ b/src/physics/carma/base @@ -1 +1 @@ -Subproject commit bf165cd84ef94087d9a5669a5ad47838ab24c0ef +Subproject commit 67418505b48787bd305a50ffb581f98f0b466cba diff --git a/src/physics/carma/cam/carma_constants_mod.F90 b/src/physics/carma/cam/carma_constants_mod.F90 index e7392cc6a5..c29820d382 100644 --- a/src/physics/carma/cam/carma_constants_mod.F90 +++ b/src/physics/carma/cam/carma_constants_mod.F90 @@ -119,9 +119,9 @@ module carma_constants_mod !! NWAVE should be the total number of bands CAM supports. integer, public, parameter :: NWAVE = nlwbands+nswbands ! Number of wavelength bands - - - + !! The maximum number of diagnostic values that can be returned by + !! CARMA_CalculateCloudborneDiagnostics + integer, public, parameter :: MAXCLDAERDIAG = 16 !! These are constants per CARMA's definition, but are set dynamically in CAM and thus !! can not be set as constants. They must be initialized as variables in carma_init. @@ -147,5 +147,4 @@ module carma_constants_mod !! Define ratio of gas constant for dry air and specific heat real(kind=f) :: RKAPPA - -end module +end module carma_constants_mod diff --git a/src/physics/carma/cam/carma_intr.F90 b/src/physics/carma/cam/carma_intr.F90 index e726c296c9..9e86637b0c 100644 --- a/src/physics/carma/cam/carma_intr.F90 +++ b/src/physics/carma/cam/carma_intr.F90 @@ -11,7 +11,7 @@ module carma_intr use carma_precision_mod use carma_enums_mod - use carma_constants_mod + use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA use carma_types_mod use carma_flags_mod use carma_model_mod @@ -23,25 +23,18 @@ module carma_intr use carma_mod use shr_kind_mod, only: r8 => shr_kind_r8 - use spmd_utils, only: masterproc - use pmgrid, only: plat, plev, plevp, plon + use spmd_utils, only: masterproc, mpicom use ppgrid, only: pcols, pver, pverp use ref_pres, only: pref_mid, pref_edge, pref_mid_norm, psurf_ref use physics_types, only: physics_state, physics_ptend, physics_ptend_init, & set_dry_to_wet, physics_state_copy - use phys_grid, only: get_lat_all_p - use physconst, only: avogad, cpair + use physconst, only: cpair use constituents, only: pcnst, cnst_add, cnst_get_ind, & - cnst_name, cnst_longname, cnst_type - use chem_surfvals, only: chem_surfvals_get + cnst_name, cnst_longname use cam_abortutils, only: endrun use physics_buffer, only: physics_buffer_desc, pbuf_add_field, pbuf_old_tim_idx, & - pbuf_get_index, pbuf_get_field, dtype_r8 - - -#if ( defined SPMD ) - use mpishorthand -#endif + pbuf_get_index, pbuf_get_field, dtype_r8, pbuf_set_field + use pio, only: var_desc_t implicit none @@ -61,17 +54,20 @@ module carma_intr public carma_timestep_tend ! interface to tendency computation public carma_accumulate_stats ! collect stats from all MPI tasks + ! Other Microphysics public carma_emission_tend ! calculate tendency from emission source function public carma_wetdep_tend ! calculate tendency from wet deposition - + public :: carma_restart_init + public :: carma_restart_write + public :: carma_restart_read ! Private data ! Particle Group Statistics ! Gridbox average - integer, parameter :: NGPDIAGS = 12 ! Number of particle diagnostics ... + integer, parameter :: NGPDIAGS = 13 ! Number of particle diagnostics ... integer, parameter :: GPDIAGS_ND = 1 ! Number density integer, parameter :: GPDIAGS_AD = 2 ! Surface area density integer, parameter :: GPDIAGS_MD = 3 ! Mass density @@ -84,10 +80,15 @@ module carma_intr integer, parameter :: GPDIAGS_VM = 10 ! Mass Weighted Fall Velocity integer, parameter :: GPDIAGS_PA = 11 ! Projected Area integer, parameter :: GPDIAGS_AR = 12 ! Area Ratio + integer, parameter :: GPDIAGS_VR = 13 ! Volatile Mixing Ratio ! Particle Bin (Element) Statistics - integer, parameter :: NBNDIAGS = 1 ! Number of bin surface diagnostics ... + integer, parameter :: NBNDIAGS = 5 ! Number of bin surface diagnostics ... integer, parameter :: BNDIAGS_TP = 1 ! Delta Particle Temperature [K] + integer, parameter :: BNDIAGS_WETR = 2 ! wet radius + integer, parameter :: BNDIAGS_ND = 3 ! Number density + integer, parameter :: BNDIAGS_RO = 4 ! particle density + integer, parameter :: BNDIAGS_VR = 5 ! Volatile Mixing Ratio ! Surface integer, parameter :: NSBDIAGS = 2 ! Number of bin surface diagnostics ... @@ -134,16 +135,19 @@ module carma_intr ! Physics Buffer Indicies - integer :: ipbuf4gas(NGAS) ! physics buffer index for a carma gas - integer :: ipbuf4t ! physics buffer index for a carma temperature - integer :: ipbuf4sati(NGAS) ! physics buffer index for a carma saturation over ice - integer :: ipbuf4satl(NGAS) ! physics buffer index for a carma saturation over liquid + integer :: ipbuf4gas(NGAS)=-1 ! physics buffer index for a carma gas + integer :: ipbuf4t=-1 ! physics buffer index for a carma temperature + integer :: ipbuf4sati(NGAS)=-1 ! physics buffer index for a carma saturation over ice + integer :: ipbuf4satl(NGAS)=-1 ! physics buffer index for a carma saturation over liquid ! Globals used for a reference atmosphere. - real(kind=f) :: carma_t_ref(pver) ! midpoint temperature (Pa) - real(kind=f) :: carma_h2o_ref(pver) ! h2o mmmr (kg/kg) - real(kind=f) :: carma_h2so4_ref(pver) ! h2so4 mmr (kg/kg) + real(kind=f) :: carma_t_ref(pver) = -huge(1._f) ! midpoint temperature (Pa) + real(kind=f) :: carma_h2o_ref(pver) = -huge(1._f) ! h2o mmmr (kg/kg) + real(kind=f) :: carma_h2so4_ref(pver) = -huge(1._f) ! h2so4 mmr (kg/kg) + type(var_desc_t) :: t_ref_desc + type(var_desc_t) :: h2o_ref_desc + type(var_desc_t) :: h2so4_ref_desc ! Globals used for total statistics real(kind=f) :: glob_max_nsubstep = 0._f @@ -158,7 +162,6 @@ module carma_intr real(kind=f) :: step_nsubstep = 0._f real(kind=f) :: step_nretry = 0._f - contains @@ -177,8 +180,7 @@ module carma_intr !! @author Chuck Bardeen !! @version May-2009 subroutine carma_register - use radconstants, only : nswbands, nlwbands, & - get_sw_spectral_boundaries, get_lw_spectral_boundaries + use radconstants, only : nlwbands, get_sw_spectral_boundaries, get_lw_spectral_boundaries use cam_logfile, only : iulog use cam_control_mod, only : initial_run use physconst, only: gravit, p_rearth=>rearth, mwdry, mwh2o @@ -251,19 +253,19 @@ subroutine carma_register ! Create the CARMA object that will contain all the information about the ! how CARMA is configured. - call CARMA_Create(carma, NBIN, NELEM, NGROUP, NSOLUTE, NGAS, NWAVE, rc, & - LUNOPRT=LUNOPRT, wave=wave, dwave=dwave, do_wave_emit=do_wave_emit) + LUNOPRT=LUNOPRT, wave=wave, dwave=dwave, do_wave_emit=do_wave_emit, NREFIDX=NREFIDX) if (rc < 0) call endrun('carma_register::CARMA_Create failed.') ! Define the microphysical model. - call CARMA_DefineModel(carma, rc) + call CARMAMODEL_DefineModel(carma, rc) if (rc < 0) call endrun('carma_register::CARMA_DefineModel failed.') if (masterproc) then write(LUNOPRT,*) '' write(LUNOPRT,*) 'CARMA general settings for ', trim(carma_model), ' model : ' write(LUNOPRT,*) ' carma_do_aerosol = ', carma_do_aerosol + write(LUNOPRT,*) ' carma_do_coremasscheck = ',carma_do_coremasscheck write(LUNOPRT,*) ' carma_do_cldice = ', carma_do_cldice write(LUNOPRT,*) ' carma_do_cldliq = ', carma_do_cldliq write(LUNOPRT,*) ' carma_do_clearsky = ', carma_do_clearsky @@ -297,8 +299,8 @@ subroutine carma_register write(LUNOPRT,*) ' carma_maxretries = ', carma_maxretries write(LUNOPRT,*) ' carma_vf_const = ', carma_vf_const write(LUNOPRT,*) ' cldfrc_incloud = ', CLDFRC_INCLOUD - write(LUNOPRT,*) ' carma_reftfile = ', trim(carma_reftfile) write(LUNOPRT,*) ' carma_rad_feedback = ', carma_rad_feedback + write(LUNOPRT,*) ' carma_sulfnuc_method = ', carma_sulfnuc_method write(LUNOPRT,*) '' endif @@ -309,6 +311,8 @@ subroutine carma_register ! assumptions made in the CAM energy checking and microphysics code. call CARMA_Initialize(carma, & rc, & + sulfnucl_method = carma_sulfnuc_method, & + do_coremasscheck = carma_do_coremasscheck, & do_clearsky = carma_do_clearsky, & do_cnst_rlh = .true., & do_coag = carma_do_coag, & @@ -338,7 +342,6 @@ subroutine carma_register tstick = carma_tstick) if (rc < 0) call endrun('carma_register::CARMA_Initialize failed.') - ! The elements and gases from CARMA need to be added as constituents in ! CAM (if they don't already exist). For the elements, each radius bin ! needs to be its own constiuent in CAM. @@ -362,16 +365,14 @@ subroutine carma_register ! For prognostic groups, all of the bins need to be represented as actual CAM ! constituents. Diagnostic groups are determined from state information that ! is already present in CAM, and thus their bins only exist in CARMA. - if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then - - do ibin = 1, NBIN + do ibin = 1, NBIN + write(btndname(igroup, ibin), '(A, I2.2)') trim(grp_short), ibin + if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then ! Bins past maxbin are treated as diagnostic even if the group ! is prognostic and thus are not advected in the paerent model. if (ibin <= maxbin) then - write(btndname(igroup, ibin), '(A, I2.2)') trim(grp_short), ibin - write(c_name, '(A, I2.2)') trim(shortname), ibin write(c_longname, '(A, e11.4, A)') trim(name) // ', ', r(ibin)*1.e4_r8, ' um' @@ -381,8 +382,8 @@ subroutine carma_register call cnst_add(c_name, WTMOL_AIR, cpair, 0._r8, icnst4elem(ielem, ibin), & longname=c_longname, mixtype=carma_mixtype, is_convtran1=is_convtran1(igroup)) end if - end do - end if + end if + end do end do ! Find the constituent for the gas or add it if not found. @@ -508,16 +509,14 @@ end function carma_implements_cnst !! !! @author Chuck Bardeen !! @version May 2009 - subroutine carma_init + subroutine carma_init(pbuf2d) use cam_history, only: addfld, add_default, horiz_only - use ioFileMod, only : getfil use wrap_nf use time_manager, only: is_first_step use phys_control, only: phys_getopts - implicit none + type(physics_buffer_desc), pointer :: pbuf2d(:,:) - integer :: iz ! vertical index integer :: ielem ! element index integer :: ibin ! bin index integer :: igas ! gas index @@ -529,15 +528,10 @@ subroutine carma_init integer :: maxbin ! last prognostic bin logical :: is_cloud ! is the group a cloud? logical :: do_drydep ! is dry deposition enabled? + integer :: ncore ! number of core elements in the group - integer :: ier - integer :: ncid, dimid_lev, vid_T - logical :: lexist - character(len=256) :: locfn - integer :: nlev - integer :: LUNOPRT ! logical unit number for output - logical :: do_print ! do print output? logical :: history_carma + logical :: history_carma_srf_flx 1 format(a6,4x,a11,4x,a11,4x,a11) 2 format(i6,4x,3(1pe11.3,4x)) @@ -546,6 +540,7 @@ subroutine carma_init rc = 0 call phys_getopts(history_carma_out=history_carma) + history_carma_srf_flx = .false. ! Set names of constituent sources and declare them as history variables; howver, ! only prognostic variables have. @@ -589,9 +584,18 @@ subroutine carma_init call addfld(trim(etndname(ielem, ibin))//'SW', horiz_only, 'A', 'kg/m2/s', & trim(cnst_name(icnst)) // ' wet deposition flux at surface') + if (history_carma_srf_flx) then + call add_default(trim(etndname(ielem, ibin))//'EM', 1, ' ') + call add_default(trim(etndname(ielem, ibin))//'SF', 1, ' ') + call add_default(trim(etndname(ielem, ibin))//'SW', 1, ' ') + end if + if (do_drydep) then - call addfld(trim(etndname(ielem, ibin))//'DD', horiz_only, 'A', 'kg/m2/s ', & - trim(cnst_name(icnst)) // ' dry deposition') + call addfld(trim(etndname(ielem, ibin))//'DD', horiz_only, 'A', 'kg/m2/s ', & + trim(cnst_name(icnst)) // ' dry deposition') + if (history_carma_srf_flx) then + call add_default(trim(etndname(ielem, ibin))//'DD', 1, ' ') + end if end if if (carma_do_pheat) then @@ -604,7 +608,7 @@ subroutine carma_init end do do igroup = 1, NGROUP - call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep) + call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep, ncore=ncore) if (rc < 0) call endrun('carma_init::CARMAGROUP_GetGroup failed.') ! Gridbox average @@ -623,6 +627,7 @@ subroutine carma_init call addfld(trim(sname)//'PA', (/ 'lev' /), 'A', 'cm2', trim(sname) // ' projected area') call addfld(trim(sname)//'AR', (/ 'lev' /), 'A', ' ', trim(sname) // ' area ratio') call addfld(trim(sname)//'VM', (/ 'lev' /), 'A', 'm/s', trim(sname) // ' fall velocity') + call addfld(trim(sname)//'VR', (/ 'lev' /), 'A', 'kg/kg', trim(sname) // ' volatile mass mixing ratio') if (history_carma) then call add_default(trim(sname)//'ND', 1, ' ') @@ -636,6 +641,7 @@ subroutine carma_init call add_default(trim(sname)//'PA', 1, ' ') call add_default(trim(sname)//'AR', 1, ' ') call add_default(trim(sname)//'VM', 1, ' ') + call add_default(trim(sname)//'VR', 1, ' ') if (carma_do_grow) then call add_default(trim(sname)//'JN', 1, ' ') @@ -644,12 +650,39 @@ subroutine carma_init ! Per bin stats .. if (do_drydep) then - do ibin = 1, NBIN - call addfld(trim(btndname(igroup, ibin))//'VD', horiz_only, 'A', 'm/s', & - trim(btndname(igroup, ibin))//' dry deposition velocity') - end do + do ibin = 1, NBIN + call addfld(trim(btndname(igroup, ibin))//'VD', horiz_only, 'A', 'm/s', & + trim(btndname(igroup, ibin)) // ' dry deposition velocity') + end do end if + do ibin = 1, NBIN + call addfld(trim(btndname(igroup, ibin))//'ND', (/ 'lev' /), 'A', '#/cm3', & + trim(btndname(igroup, ibin)) // ' number density') + call addfld(trim(btndname(igroup, ibin))//'WR', (/ 'lev' /), 'A', 'um', & + trim(btndname(igroup, ibin)) // ' wet radius') + call addfld(trim(btndname(igroup, ibin))//'RO', (/ 'lev' /), 'A', 'g/cm3', & + trim(btndname(igroup, ibin)) // ' wet particle density') + call addfld(trim(btndname(igroup, ibin))//'VR', (/ 'lev' /), 'A', 'um', & + trim(btndname(igroup, ibin)) // ' volatile mixing ratio') + + + if ((carma_ndebugpkgs > 0) .and. (ncore > 0)) then + call addfld(trim(btndname(igroup, ibin))//'LCFM', horiz_only, 'A', 'kg/m2', trim(btndname(igroup, ibin)) // ' CARMA local mass fixer fail mass ') + call addfld(trim(btndname(igroup, ibin))//'LCFP', horiz_only, 'A', 'probability', trim(btndname(igroup, ibin)) // ' CARMA mass local fail PDF') + call addfld(trim(btndname(igroup, ibin))//'LCR', (/ 'lev' /), 'A', 'kg/kg', trim(btndname(igroup, ibin)) // ' CARMA local mass fix MMR') + call addfld(trim(btndname(igroup, ibin))//'LCP', (/ 'lev' /), 'A', 'probability', trim(btndname(igroup, ibin)) // ' CARMA local fix PDF') + + if (carma_diags_file > 0) then + call add_default(trim(btndname(igroup, ibin))//'LCFM', carma_diags_file, ' ') + call add_default(trim(btndname(igroup, ibin))//'LCFP', carma_diags_file, ' ') + call add_default(trim(btndname(igroup, ibin))//'LCR', carma_diags_file, ' ') + call add_default(trim(btndname(igroup, ibin))//'LCP', carma_diags_file, ' ') + end if + end if + + end do + end do do igas = 1, NGAS @@ -708,105 +741,20 @@ subroutine carma_init if (carma%f_igash2o /= 0) call carma_getH2O(carma_h2o_ref) if (carma%f_igash2So4 /= 0) call carma_getH2SO4(carma_h2so4_ref) end if - - if (masterproc) then - call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun('carma_init::CARMA_Get failed.') - - if (do_print) write(LUNOPRT,*) "" - if (do_print) write(LUNOPRT,*) "CARMA initializing to fixed reference state." - if (do_print) write(LUNOPRT,*) "" - - ! For temperature, get the average temperature from reference temperature file - ! if it exists or from the initial condition file if the reference temperature file - ! doesn't exist. - ! - ! NOTE: The reference temperature file will only be created for an inital run. It - ! must already exist for a restart run. - - ! Does reference temperature file already exist? - call getfil(carma_reftfile, locfn, iflag=1) - - inquire(file=locfn, exist=lexist) - - ! Read the reference temperature from the file. - if (lexist) then - - ! Open the netcdf file. - call wrap_open(trim(locfn), NF90_NOWRITE, ncid) - - ! Inquire about dimensions - call wrap_inq_dimid(ncid, 'lev', dimid_lev) - call wrap_inq_dimlen(ncid, dimid_lev, nlev) - - ! Does the number of levels match? - if (nlev /= pver) then - call endrun("carma_init::ERROR - Incompatible number of levels & - &in the CARMA reference temperature file ... " // trim(locfn)) - end if - - ! Get variable ID for reference temperature - call wrap_inq_varid(ncid, 'T', vid_T) - - ! Read in the temperature data. - call wrap_get_var_realx(ncid, vid_T, carma_T_ref) - - if (carma%f_igash2o /= 0) then - ! Get variable ID for reference temperature - call wrap_inq_varid(ncid, 'Q', vid_T) - - ! Read in the temperature data. - call wrap_get_var_realx(ncid, vid_T, carma_h2o_ref) - end if - - if (carma%f_igash2so4 /= 0) then - ! Get variable ID for reference temperature - call wrap_inq_varid(ncid, 'H2SO4', vid_T) - - ! Read in the temperature data. - call wrap_get_var_realx(ncid, vid_T, carma_h2so4_ref) - end if - - ! Close the file - call wrap_close(ncid) - - ! Is this an initial or restart run? - else if (is_first_step()) then - - if (do_print) write(LUNOPRT,*) "" - if (do_print) write(LUNOPRT,*) 'Creating CARMA reference temperature file ... ', trim(locfn) - - ! Save the average into a file to be used for restarts. - call CARMA_CreateRefTFile(carma, locfn, pref_mid(:) / 100._r8, & - carma_t_ref(:), rc, refh2o=carma_h2o_ref(:), refh2so4=carma_h2so4_ref(:)) - else - - ! The file must already exist for a restart run. - call endrun("carma_init::ERROR - Can't find the CARMA reference temperature file ... " // trim(carma_reftfile)) - - end if - - ! Write out the values that are being used. - if (do_print) write(LUNOPRT,*) "" - if (do_print) write(LUNOPRT,1) "Level","Int P (Pa)","Mid P (Pa)","Mid T (K)" - - do iz = 1, pver - if (do_print) write(LUNOPRT,2) iz, pref_edge(iz), pref_mid(iz), carma_t_ref(iz) - end do - if (do_print) write(LUNOPRT,2) iz, pref_edge(iz), 0.0_r8, 0.0_r8 - if (do_print) write(LUNOPRT,*) "" - end if - -#ifdef SPMD - - ! Communicate the settings to the other MPI tasks. - call mpi_bcast(carma_t_ref, pver, MPI_REAL8, 0, mpicom, ier) -#endif end if + if (is_first_step()) then + ! initialize physics buffer fields + do igas = 1, NGAS + call pbuf_set_field(pbuf2d, ipbuf4gas(igas), 0.0_r8) + call pbuf_set_field(pbuf2d, ipbuf4sati(igas), 0.0_r8) + call pbuf_set_field(pbuf2d, ipbuf4satl(igas), 0.0_r8) + end do + call pbuf_set_field(pbuf2d, ipbuf4t, 0.0_r8) + endif ! Do a model specific initialization. - call CARMA_InitializeModel(carma, lq_carma, rc) + call CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) if (rc < 0) call endrun('carma_init::CARMA_InitializeModel failed.') return @@ -846,9 +794,9 @@ subroutine carma_final glob_nretry / glob_nstep else if (do_print) write(LUNOPRT,2) glob_max_nsubstep, & - 0., & + 0._r8, & glob_max_nretry, & - 0. + 0._r8 end if end if end if @@ -902,7 +850,7 @@ end subroutine carma_timestep_init !! @version May-2009 subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rliq, prec_str, snow_str, & prec_sed, snow_sed, ustar, obklen) - use time_manager, only: get_nstep, get_step_size, is_first_step + use time_manager, only: get_nstep, is_first_step use camsrfexch, only: cam_in_t, cam_out_t use planck, only: planckIntensity @@ -968,9 +916,12 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli real(r8) :: ar(pver) ! Area Ratio real(r8) :: vm(pver) ! Massweighted fall velocity (cm2) real(r8) :: jn(pver) ! nucleation (cm-3) + real(r8) :: totalmmr(pver) ! total particle mmr (kg/kg) real(r8) :: numberDensity(pver) ! number density (cm-3) real(r8) :: nucleationRate(pver) ! nucleation rate (cm-3 s-1) real(r8) :: extinctionCoefficient(pver) ! extinction coefficient (cm2) + real(r8) :: r_wet(pver) ! wet radius (um) + real(r8) :: rhop_wet(pver) ! wet particle density (g/cm3) real(r8) :: dd ! dry deposition (kg/m2) real(r8) :: vd ! dry deposition velocity (cm/s) real(r8) :: vf(pverp) ! fall velocity (cm/s) @@ -986,7 +937,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli real(r8), pointer, dimension(:,:) :: tnd_qsnow ! external tendency on snow mass (kg/kg/s) real(r8), pointer, dimension(:,:) :: tnd_nsnow ! external tendency on snow number(#/kg/s) real(r8), pointer, dimension(:,:) :: re_ice ! ice effective radius (m) - integer :: lchnk ! chunk identifier integer :: iz real(r8) :: cldfrc(pver) ! cloud fraction [fraction] real(r8) :: rhcrit(pver) ! relative humidity for onset of liquid clouds [fraction] @@ -1010,7 +960,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli logical :: is_ice ! is the group ice? logical :: grp_do_drydep ! is dry depostion enabled for group? logical :: do_drydep ! is dry depostion enabled? - logical :: do_fixedinit ! do initialization from reference atm? logical :: do_detrain ! do convective detrainment? integer :: iwvl real(r8), parameter :: zzocen = 0.0001_r8 ! Ocean aerodynamic roughness length [m] @@ -1048,8 +997,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli call cnst_get_ind('Q', icnst_q) ! Get pointers into pbuf ... - lchnk = state_loc%lchnk - call pbuf_get_field(pbuf, ipbuf4t, t_ptr) ! If doing particle heating, then get pointers to the spectral flux data provided @@ -1080,11 +1027,10 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli ! If initializing CARMASTATE from a reference state, do it before entering the main ! loop. ! - call CARMA_Get(carma, rc, do_fixedinit=do_fixedinit, do_drydep=do_drydep) + call CARMA_Get(carma, rc, do_drydep=do_drydep) if (rc < 0) call endrun('carma_timestep_tend::CARMA_Get failed.') - if (do_fixedinit) then - + if (carma_do_fixedinit) then call CARMASTATE_CreateFromReference(cstate, & carma_ptr, & time, & @@ -1101,7 +1047,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli rc, & qh2o=carma_h2o_ref, & qh2so4=carma_h2so4_ref) - if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_CreateFromReference failed.') + if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_CreateFromReference failed.') end if @@ -1227,7 +1173,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli end do - call CARMA_DiagnoseBins(carma, cstate, state_loc, pbuf, icol, dt, rc, rliq=rliq, prec_str=prec_str, snow_str=snow_str) + call CARMAMODEL_DiagnoseBins(carma, cstate, state_loc, pbuf, icol, dt, rc, rliq=rliq, prec_str=prec_str, snow_str=snow_str) if (rc < 0) call endrun('carma_timestep_tend::CARMA_DiagnoseBins failed.') @@ -1237,7 +1183,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli if (rc < 0) call endrun('CARMA_Detrain::CARMA_Get failed.') if (do_detrain) then - call CARMA_Detrain(carma, cstate, cam_in, dlf, state_loc, icol, dt, rc, rliq=rliq, prec_str=prec_str, & + call CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state_loc, icol, dt, rc, rliq=rliq, prec_str=prec_str, & snow_str=snow_str, tnd_qsnow=tnd_qsnow, tnd_nsnow=tnd_nsnow) if (rc < 0) call endrun('carma_timestep_tend::CARMA_Detrain failed.') end if @@ -1312,11 +1258,11 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli ! NOTE: To work around an XL Fortran compiler bug, the optional arguments can only ! be passed when defined. if (present(rliq)) then - call CARMA_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc, & + call CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc, & rliq=rliq, prec_str=prec_str, snow_str=snow_str, prec_sed=prec_sed, & snow_sed=snow_sed, tnd_qsnow=tnd_qsnow, tnd_nsnow=tnd_nsnow, re_ice=re_ice) else - call CARMA_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc) + call CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc) end if if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_DiagnoseBulk failed.') @@ -1351,7 +1297,8 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli do ibin = 1, NBIN call CARMASTATE_GetBin(cstate, ielem, ibin, newstate(:), rc, & - numberDensity=numberDensity, nucleationRate=nucleationRate, surface=dd, vd=vd, vf=vf, dtpart=dtpart) + numberDensity=numberDensity, nucleationRate=nucleationRate, r_wet=r_wet, & + rhop_wet=rhop_wet, sedimentationflux=dd, vd=vd, vf=vf, dtpart=dtpart, totalmmr=totalmmr) if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_GetBin failed.') ! For prognostic groups, set the tendency from the corresponding constituents. @@ -1367,7 +1314,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli ptend%q(icol, :, icnst) = (newstate(:) - state_loc%q(icol, :, icnst)) / dt if (grp_do_drydep) then - sbdiags(icol, ibin, ielem, SBDIAGS_DD) = dd / dt + sbdiags(icol, ibin, ielem, SBDIAGS_DD) = dd sbdiags(icol, ibin, ielem, SBDIAGS_VD) = - vd / 100._r8 end if end if @@ -1382,7 +1329,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli re3(:) = re3(:) + numberDensity(:) * ((r(ibin)*rrat(ibin))**3) ad(:) = ad(:) + numberDensity(:) * 4.0_r8 * PI * (r(ibin)**2) * 1.0e8_r8 md(:) = md(:) + numberDensity(:) * rmass(ibin) - mr(:) = mr(:) + newstate(:) + mr(:) = mr(:) + totalmmr(:) pa(:) = pa(:) + numberDensity(:) * PI * ((r(ibin) * rrat(ibin))**2) * arat(ibin) vm(:) = vm(:) + numberDensity(:) * rmass(ibin) * vf(2:) / 100._f @@ -1397,6 +1344,9 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli od(:) = od(:) + numberDensity(:) * extinctionCoefficient(:) * dz(:) * 100._r8 end if + bndiags(icol,:,ibin,ielem,BNDIAGS_VR) = bndiags(icol,:,ibin,ielem,BNDIAGS_VR) + totalmmr(:) + gpdiags(icol, :, igroup, GPDIAGS_VR) = gpdiags(icol, :, igroup, GPDIAGS_VR) + totalmmr(:) + ! Particle temperatures from particle heating. if (carma_do_pheat) then bndiags(icol, :, ibin, ielem, BNDIAGS_TP) = dtpart(:) @@ -1405,6 +1355,12 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli if (nucleationRate(1) /= CAM_FILL) then jn(:) = jn(:) + nucleationRate(:) end if + + ! Output nd and wet radius for each bin. + r_wet = r_wet * 1e4_r8 ! cm to um + bndiags(icol,:,ibin,ielem,BNDIAGS_WETR) = r_wet(:) + bndiags(icol,:,ibin,ielem,BNDIAGS_ND) = numberDensity(:) + bndiags(icol,:,ibin,ielem,BNDIAGS_RO) = rhop_wet(:) end do ! If this is the number element for the group, then write out the @@ -1454,7 +1410,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli call pbuf_get_field(pbuf, ipbuf4satl(igas), satl_ptr) call CARMASTATE_GetGas(cstate, igas, newstate(:), rc, satice=satice, satliq=satliq, & - eqice=eqice, eqliq=eqliq, wtpct=wtpct) + eqice=eqice, eqliq=eqliq, wtpct=wtpct) if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_GetGas failed.') icnst = icnst4gas(igas) @@ -1492,7 +1448,9 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_Get failed.') spdiags(icol, :, SPDIAGS_NSTEP) = zsubsteps(:) - spdiags(icol, :, SPDIAGS_LNSTEP) = log(zsubsteps(:)) + where (zsubsteps/=0.0_r8) + spdiags(icol, :, SPDIAGS_LNSTEP) = log(zsubsteps(:)) + end where end if end do @@ -1517,14 +1475,35 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli call CARMASTATE_Destroy(cstate, rc) if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_Destroy failed.') - ! Output diagnostic fields. - call carma_output_diagnostics(state_loc, ptend, gpdiags, sbdiags, gsdiags, spdiags, bndiags) + call carma_output_diagnostics(state_loc, ptend, pbuf, cam_in, gpdiags, sbdiags, gsdiags, spdiags, bndiags) end subroutine carma_timestep_tend + !! Get the index for the constituents array for the specified bin + !! of the specified element. + !! + !! @author Yunqian Zhu, Francis Vitt + !! @version September-2022 + subroutine carma_getcnstforbin(ielem, ibin, icnst) + implicit none + + integer, intent(in) :: ielem, ibin + integer, intent(out) :: icnst + + icnst = icnst4elem(ielem,ibin) + return + end subroutine carma_getcnstforbin + + !! Collect CARMA substep statistics from all MPI tasks. + !! + !! @author Chuck Bardeen + !! @version May-2009 subroutine carma_accumulate_stats() +#if ( defined SPMD ) + use mpishorthand +#endif implicit none integer :: istat @@ -1600,9 +1579,9 @@ subroutine carma_accumulate_stats() step_nretry / step_nstep else if (do_print) write(LUNOPRT,1) step_max_nsubstep, & - 0., & + 0._r8, & step_max_nretry, & - 0. + 0._r8 end if end if end if @@ -1665,7 +1644,7 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q) end where end do - call CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + call CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) if (rc < 0) call endrun('carma_init_cnst::CARMA_InitializeParticle failed.') end if end if @@ -1679,19 +1658,21 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q) return end subroutine carma_init_cnst - !! Outputs tracer tendencies and diagnositc fields to the history files. !! All the columns in the chunk should be output at the same time. !! !! @author Chuck Bardeen !! @version May-2009 - subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spdiags, bndiags) + subroutine carma_output_diagnostics(state, ptend, pbuf, cam_in, gpdiags, sbdiags, gsdiags, spdiags, bndiags) use cam_history, only: outfld + use camsrfexch, only: cam_in_t implicit none type(physics_state), intent(in) :: state !! Physics state variables - before CARMA type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(in), dimension(pcols, pver, NGROUP, NGPDIAGS) :: gpdiags !! CARMA group diagnostic output real(r8), intent(in), dimension(pcols, NBIN, NELEM, NSBDIAGS) :: sbdiags !! CARMA surface bin diagnostic output real(r8), intent(in), dimension(pcols, pver, NGAS, NGSDIAGS) :: gsdiags !! CARMA gas diagnostic output @@ -1706,7 +1687,6 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd integer :: ienconc ! element index for group's concentration element integer :: icnst ! constituent index integer :: lchnk ! chunk identifier - integer :: ncol ! number of columns integer :: rc ! CARMA return code character(len=8) :: sname ! short (CAM) name integer :: cnsttype ! constituent type @@ -1714,12 +1694,13 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd logical :: is_cloud ! is the group a cloud? logical :: do_drydep ! is dry deposition enabled? + character(len=*), parameter :: subname = 'carma_output_diagnostics' + ! Initialize the return code. rc = 0 ! Check each column int the chunk. lchnk = state%lchnk - ncol = state%ncol ! Output step diagnostics. if (carma_do_substep) then @@ -1732,10 +1713,10 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd do ibin = 1, NBIN call CARMAELEMENT_Get(carma, ielem, rc, igroup=igroup) - if (rc < 0) call endrun('carma_timestep_tend::CARMAELEMENT_Get failed.') + if (rc < 0) call endrun(subname//'::CARMAELEMENT_Get failed.') call CARMAGROUP_Get(carma, igroup, rc, cnsttype=cnsttype, maxbin=maxbin, do_drydep=do_drydep) - if (rc < 0) call endrun('carma_timestep_tend::CARMAGROUP_Get failed.') + if (rc < 0) call endrun(subname//'::CARMAGROUP_Get failed.') if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then @@ -1766,7 +1747,7 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd ! Output the particle diagnostics. do igroup = 1, NGROUP call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep, ienconc=ienconc) - if (rc < 0) call endrun('carma_output_diagnostics::CARMAGROUP_Get failed.') + if (rc < 0) call endrun(subname//'::CARMAGROUP_Get failed.') ! Gridbox average call outfld(trim(sname)//'ND', gpdiags(:, :, igroup, GPDIAGS_ND), pcols, lchnk) @@ -1781,12 +1762,20 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd call outfld(trim(sname)//'PA', gpdiags(:, :, igroup, GPDIAGS_PA), pcols, lchnk) call outfld(trim(sname)//'AR', gpdiags(:, :, igroup, GPDIAGS_AR), pcols, lchnk) call outfld(trim(sname)//'VM', gpdiags(:, :, igroup, GPDIAGS_VM), pcols, lchnk) + call outfld(trim(sname)//'VR', gpdiags(:, :, igroup, GPDIAGS_VR), pcols, lchnk) if (do_drydep) then do ibin = 1, NBIN call outfld(trim(btndname(igroup, ibin))//'VD', sbdiags(:, ibin, ienconc, SBDIAGS_VD), pcols, lchnk) end do end if + + do ibin = 1,NBIN + call outfld(trim(btndname(igroup, ibin))//'ND',bndiags(:, :, ibin, ienconc, BNDIAGS_ND), pcols, lchnk) + call outfld(trim(btndname(igroup, ibin))//'WR',bndiags(:, :, ibin, ienconc, BNDIAGS_WETR), pcols, lchnk) + call outfld(trim(btndname(igroup, ibin))//'RO',bndiags(:, :, ibin, ienconc, BNDIAGS_RO), pcols, lchnk) + call outfld(trim(btndname(igroup, ibin))//'VR',bndiags(:, :, ibin, ienconc, BNDIAGS_VR), pcols, lchnk) + end do end do ! Output the gas tendencies. @@ -1808,19 +1797,21 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd call outfld('CRTT', ptend%s(:, :) / cpair, pcols, lchnk) end if + ! Allow models to output their own diagnostics + call CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + return end subroutine carma_output_diagnostics - !! Calculate the emissions for CARMA aerosols. This is taken from !! the routine aerosol_emis_intr in aerosol_intr.F90 and dust_emis_intr in !! dust_intr.F90 by Phil Rasch. !! !! @author Chuck Bardeen !! @version May-2009 - subroutine carma_emission_tend (state, ptend, cam_in, dt) - use cam_history, only: outfld - use camsrfexch, only: cam_in_t + subroutine carma_emission_tend (state, ptend, cam_in, dt, pbuf) + use cam_history, only: outfld + use camsrfexch, only: cam_in_t implicit none @@ -1828,6 +1819,7 @@ subroutine carma_emission_tend (state, ptend, cam_in, dt) type(physics_ptend), intent(inout) :: ptend !! physics state tendencies type(cam_in_t), intent(inout) :: cam_in !! surface inputs real(r8), intent(in) :: dt !! time step (s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer :: lchnk ! chunk identifier integer :: ncol ! number of columns in chunk @@ -1873,7 +1865,7 @@ subroutine carma_emission_tend (state, ptend, cam_in, dt) icnst = icnst4elem(ielem, ibin) - call CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + call CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) if (rc < 0) call endrun('carma_emission_tend::CARMA_EmitParticle failed.') ! Add any surface flux here. @@ -1908,7 +1900,6 @@ end subroutine carma_emission_tend subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) use cam_history, only: outfld use phys_control, only: cam_physpkg_is - use phys_grid, only: get_lat_all_p, get_lon_all_p, get_rlat_all_p use wetdep, only: clddiag, wetdepa_v1, wetdepa_v2 use camsrfexch, only: cam_out_t use physconst, only: gravit @@ -1942,7 +1933,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) integer :: ixcldice real(r8) :: totcond(pcols, pver) ! total condensate real(r8) :: solfac(pcols, pver) ! solubility factor - real(r8) :: solfactor + real(r8) :: solfac_in ! solubility factor real(r8) :: scavcoef ! scavenging Coefficient logical :: do_wetdep integer :: ncol ! number of columns @@ -2030,11 +2021,11 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) if (rc < 0) call endrun('carma_wetdep_tend::CARMAELEMENT_Get failed.') call CARMAGROUP_Get(carma, igroup, rc, cnsttype=cnsttype, do_wetdep=do_wetdep, & - solfac=solfactor, scavcoef=scavcoef, maxbin=maxbin) - solfac(:ncol,:) = solfactor - + solfac=solfac_in, scavcoef=scavcoef, maxbin=maxbin) if (rc < 0) call endrun('carma_wetdep_tend::CARMAGROUP_Get failed.') + solfac(:,:) = solfac_in + if ((do_wetdep) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then do ibin = 1, NBIN @@ -2099,7 +2090,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) iscavt, & cldv, & fracis(:, :, icnst), & - solfactor, & + solfac_in, & ncol, & z_scavcoef) else @@ -2122,7 +2113,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) call outfld(trim(cnst_name(icnst))//'SW', sflx, pcols, lchnk) ! Add this to the surface amount of the constituent - call CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + call CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) end if end do @@ -2138,10 +2129,114 @@ end subroutine carma_wetdep_tend !! code to include the impact of CARMA particles in the radiative transfer !! calculation. !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. + !! + !! The I_OPTICS_MIXED_YU2105 and I_OPTICS_SULFATE_YU2015 optics methods are + !! designed to trop_strat models as define in the Yu et al. (2015) paper. The + !! other optics types can be applied more generically to a number of different + !! aerosol/cloud models. + !! !! NOTE: The format of this file is determined by the needs of the radiative tranfer !! code, so ideally a routine would exist in that module that could create a file !! with the proper format. Since that doesn't exist, we do it all here. subroutine CARMA_CreateOpticsFile(carma, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + integer :: igroup + logical :: do_mie + integer :: cnsttype ! constituent type + integer :: opticsType + + ! Assume success. + rc = 0 + + ! Process each group that is defined in the model. + do igroup = 1, NGROUP + + ! Get the necessary group properties. + call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, cnsttype=cnsttype, iopticstype=opticsType) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') + + ! Are we supposed to do the mie calculation for this group? + if ((do_mie) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + ! This is for fixed composition, but the particle may swell in response + ! to changes in RH. Only one refractive index specified at the group level. + ! + ! NOTE: This is what was used by the first CARMA models that were radiatively + ! active. + case (I_OPTICS_FIXED) + call CARMA_CreateOpticsFile_Fixed(carma, igroup, rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::CreateOpticsFile_Fixed failed.') + + ! This is similar to Yu (2015) in that handles mixed particles treated as + ! core shell particles; however the dimensions of the lookup table are the + ! the radii and the refractive indicies, so it can be used with various + ! aerosol configurations (not just as in the Yu(2015)). + case(I_OPTICS_MIXED_CORESHELL) + call endrun('carma_CreateOpticsFile mixed_coreshell has not been implemented.') + + ! This is similar to MAM4, in that a volume mixing approach is used to + ! mixed both the core and the shell together and thus only one radius and + ! one refractive index are needed in the lookup table. + case(I_OPTICS_MIXED_VOLUME) + call endrun('carma_CreateOpticsFile mixed_volume has not been implemented.') + + ! This is similar to "mixed_volume", except that Maxwell-Garnett mixing + ! is used instead of volume mixing. + case(I_OPTICS_MIXED_MAXWELL) + call endrun('carma_CreateOpticsFile mixed_maxwell has not been implemented.') + + ! This is for a pure sulfate group where the table is based upon weight + ! percent; however, unlike sulfate_Yu, the refractive index of the sulfate + ! changes with the weight percent of H2SO4. + case(I_OPTICS_SULFATE) + call CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::CreateOpticsFile_Sulfate failed.') + + ! Other types are not generically useful are are particular to the + ! specific model, so thos are handled by model specific code. These + ! include: + ! I_OPTICS_MIXED_YU2015 + ! I_OPTICS_MIXED_YU_H2O + ! I_OPTICS_SULFATE_YU2015 + case default + call CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + end select + end if + end do + + return + end subroutine CARMA_CreateOpticsFile + + + !! This routine creates files containing optical properties for each radiatively + !! active particle type. These optical properties are used by the RRTMG radiation + !! code to include the impact of CARMA particles in the radiative transfer + !! calculation. + !! + !! NOTE: The format of this file is determined by the needs of the radiative tranfer + !! code, so ideally a routine would exist in that module that could create a file + !! with the proper format. Since that doesn't exist, we do it all here. + subroutine CARMA_CreateOpticsFile_Fixed(carma, igroup, rc) use radconstants, only : nswbands, nlwbands use wrap_nf use wetr, only : getwetr @@ -2149,16 +2244,17 @@ subroutine CARMA_CreateOpticsFile(carma, rc) implicit none type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group index integer, intent(out) :: rc !! return code, negative indicates failure ! Local variables - integer :: igroup, ibin, iwave, irh + integer :: ibin, iwave, irh integer :: irhswell integer :: ienconc real(kind=f) :: rho(NBIN), rhopwet real(kind=f) :: r(NBIN), rmass(NBIN), rlow(NBIN), rup(NBIN) real(kind=f) :: wave(NWAVE) - complex(kind=f) :: refidx(NWAVE) + complex(kind=f) :: refidx(NWAVE, NREFIDX) character(len=CARMA_NAME_LEN) :: name character(len=CARMA_SHORT_NAME_LEN) :: shortname logical :: do_mie @@ -2199,381 +2295,661 @@ subroutine CARMA_CreateOpticsFile(carma, rc) call CARMA_GET(carma, rc, wave=wave, do_print=do_print, LUNOPRT=LUNOPRT) if (rc < 0) call endrun('carma_CreateOpticsFile::CARMA_Get failed.') - ! Process each group that is defined in the model. - do igroup = 1, NGROUP + ! Get the necessary group properties. + call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, name=name, shortname=shortname, r=r, & + rlow=rlow, rup=rup, rmass=rmass, irhswell=irhswell, & + ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') - ! Get the necessary group properties. - call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, name=name, shortname=shortname, r=r, & - rlow=rlow, rup=rup, rmass=rmass, refidx=refidx, irhswell=irhswell, & - ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin) - if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') + call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho, refidx=refidx) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.') - ! Are we supposed to do the mie calculation for this group? - if ((do_mie) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then + ! A file needs to be created for each bin. + do ibin = 1, NBIN - call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho) - if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.') + ! Bins past maxbin are treated as diagnostic even if the group + ! is prognostic and thus are not advected in the paerent model. + if (ibin <= maxbin) then - ! A file needs to be created for each bin. - do ibin = 1, NBIN + write(c_name, '(A, I2.2)') trim(shortname), ibin - ! Bins past maxbin are treated as diagnostic even if the group - ! is prognostic and thus are not advected in the paerent model. - if (ibin <= maxbin) then + ! Construct the path to the file. Each model will have its own subdirectory + ! where the optical property files are stored. + filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc' - write(c_name, '(A, I2.2)') trim(shortname), ibin + if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath) - ! Construct the path to the file. Each model will have its own subdirectory - ! where the optical property files are stored. - filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc' + ! Create the file. + call wrap_create(filepath, NF90_CLOBBER, fid) - if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath) + ! For non-hygroscopic, only use 1 RH value. + if (irhswell /= 0) then + nrh = NMIE_RH + else + nrh = min(NMIE_RH, 1) + end if - ! Create the file. - call wrap_create(filepath, NF90_CLOBBER, fid) + ! Define the dimensions: rh, lwbands, swbands + call wrap_def_dim(fid, 'rh_idx', nrh, rhdim) + call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim) + call wrap_def_dim(fid, 'sw_band', nswbands, swdim) - ! For non-hygroscopic, only use 1 RH value. - if (irhswell /= 0) then - nrh = NMIE_RH - else - nrh = min(NMIE_RH, 1) - end if + write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band dims." - ! Define the dimensions: rh, lwbands, swbands - call wrap_def_dim(fid, 'rh_idx', nrh, rhdim) - call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim) - call wrap_def_dim(fid, 'sw_band', nswbands, swdim) + dimids(1) = rhdim + call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1:1), rhvar) - write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band dims." + dimids(1) = lwdim + call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1:1), lwvar) - dimids(1) = rhdim - call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1:1), rhvar) + dimids(1) = swdim + call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1:1), swvar) - dimids(1) = lwdim - call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1:1), lwvar) + write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band vars." - dimids(1) = swdim - call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1:1), swvar) + call wrap_put_att_text(fid, rhvar, 'units', 'fraction') + call wrap_put_att_text(fid, lwvar, 'units', 'm') + call wrap_put_att_text(fid, swvar, 'units', 'm') - write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band vars." + call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity') + call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands') + call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands') - call wrap_put_att_text(fid, rhvar, 'units', 'fraction') - call wrap_put_att_text(fid, lwvar, 'units', 'm') - call wrap_put_att_text(fid, swvar, 'units', 'm') + ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw + dimids(1) = rhdim + dimids(2) = lwdim + call wrap_def_var(fid, 'abs_lw', NF90_DOUBLE, 2, dimids, abs_lw_var) - call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity') - call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands') - call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands') + write(LUNOPRT,*) "Defined abs_lw." - ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw - dimids(1) = rhdim - dimids(2) = lwdim - call wrap_def_var(fid, 'abs_lw', NF90_DOUBLE, 2, dimids, abs_lw_var) + call wrap_put_att_text(fid, abs_lw_var, 'units', 'meter^2 kilogram^-1') - write(LUNOPRT,*) "Defined abs_lw." + dimids(1) = rhdim + dimids(2) = swdim + call wrap_def_var(fid, 'ext_sw', NF90_DOUBLE, 2, dimids, ext_sw_var) + call wrap_def_var(fid, 'ssa_sw', NF90_DOUBLE, 2, dimids, ssa_sw_var) + call wrap_def_var(fid, 'asm_sw', NF90_DOUBLE, 2, dimids, asm_sw_var) - call wrap_put_att_text(fid, abs_lw_var, 'units', 'meter^2 kilogram^-1') + write(LUNOPRT,*) "Defined ext_sw, ssa_sw, and asm_sw." - dimids(1) = rhdim - dimids(2) = swdim - call wrap_def_var(fid, 'ext_sw', NF90_DOUBLE, 2, dimids, ext_sw_var) - call wrap_def_var(fid, 'ssa_sw', NF90_DOUBLE, 2, dimids, ssa_sw_var) - call wrap_def_var(fid, 'asm_sw', NF90_DOUBLE, 2, dimids, asm_sw_var) + call wrap_put_att_text(fid, ssa_sw_var, 'units', 'fraction') + call wrap_put_att_text(fid, ext_sw_var, 'units', 'meter^2 kilogram^-1') + call wrap_put_att_text(fid, asm_sw_var, 'units', '-') - write(LUNOPRT,*) "Defined ext_sw, ssa_sw, and asm_sw." + ! Define the variables for the refractive indicies. + dimids(1) = swdim + call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_i_refidx_var) - call wrap_put_att_text(fid, ssa_sw_var, 'units', 'fraction') - call wrap_put_att_text(fid, ext_sw_var, 'units', 'meter^2 kilogram^-1') - call wrap_put_att_text(fid, asm_sw_var, 'units', '-') + write(LUNOPRT,*) "Defined lw refindex." - ! Define the variables for the refractive indicies. - dimids(1) = swdim - call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_r_refidx_var) - call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_i_refidx_var) + dimids(1) = lwdim + call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_i_refidx_var) - write(LUNOPRT,*) "Defined lw refindex." + write(LUNOPRT,*) "Defined sw refindex." - dimids(1) = lwdim - call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_r_refidx_var) - call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_i_refidx_var) + call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-') - write(LUNOPRT,*) "Defined sw refindex." + call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave') + call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave') - call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-') - call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-') - call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-') - call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-') - call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave') - call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave') - call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave') - call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave') + ! Define fields that define the aerosol properties. + call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim) + dimids(1) = omdim + call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1:1), omvar) + write(LUNOPRT,*) "Defined omdim." - ! Define fields that define the aerosol properties. - call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim) - dimids(1) = omdim - call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1:1), omvar) + call wrap_def_dim(fid, 'namelength', 20, andim) + dimids(1) = andim + call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1:1), anvar) - write(LUNOPRT,*) "Defined omdim." + write(LUNOPRT,*) "Defined aername." - call wrap_def_dim(fid, 'namelength', 20, andim) - dimids(1) = andim - call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1:1), anvar) + call wrap_def_dim(fid, 'name_len', 32, namedim) + dimids(1) = namedim + call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids(1:1), namevar) - write(LUNOPRT,*) "Defined aername." + write(LUNOPRT,*) "Defined name." - call wrap_def_dim(fid, 'name_len', 32, namedim) - dimids(1) = namedim - call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids(1:1), namevar) + call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1:0), denvar) + call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1:0), slogvar) + call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1:0), dryrvar) + call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1:0), rminvar) + call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1:0), rmaxvar) + call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1:0), hygrovar) + call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1:0), ntmvar) - write(LUNOPRT,*) "Defined name." + call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3') + call wrap_put_att_text(fid, slogvar, 'units', '-') + call wrap_put_att_text(fid, dryrvar, 'units', 'm') + call wrap_put_att_text(fid, rminvar, 'units', 'm') + call wrap_put_att_text(fid, rmaxvar, 'units', 'm') + call wrap_put_att_text(fid, hygrovar, 'units', '-') + call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1') - call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1:0), denvar) - call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1:0), slogvar) - call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1:0), dryrvar) - call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1:0), rminvar) - call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1:0), rmaxvar) - call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1:0), hygrovar) - call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1:0), ntmvar) + call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density') + call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol') + call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol') + call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin') + call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin') + call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol') + call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol') - call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3') - call wrap_put_att_text(fid, slogvar, 'units', '-') - call wrap_put_att_text(fid, dryrvar, 'units', 'm') - call wrap_put_att_text(fid, rminvar, 'units', 'm') - call wrap_put_att_text(fid, rmaxvar, 'units', 'm') - call wrap_put_att_text(fid, hygrovar, 'units', '-') - call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1') - call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density') - call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol') - call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol') - call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin') - call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin') - call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol') - call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol') + write(LUNOPRT,*) "Defined all variables." + ! End the defintion phase of the netcdf file. + call wrap_enddef(fid) - write(LUNOPRT,*) "Defined all variables." + ! Write out the dimensions. + call wrap_put_var_realx(fid, rhvar, mie_rh(:nrh)) + call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f) + call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f) - ! End the defintion phase of the netcdf file. - call wrap_enddef(fid) + ! Write out the refractive indicies. + call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidx(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidx(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidx(:nlwbands, 1))) + call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidx(:nlwbands, 1))) - ! Write out the dimensions. - call wrap_put_var_realx(fid, rhvar, mie_rh(:nrh)) - call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f) - call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f) + ! Pad the names out with spaces. + aer_name = ' ' + aer_name(1:len(trim(c_name))) = c_name + + start_text(1) = 1 + count_text(1) = 32 + call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /)) + count_text(1) = 20 + call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /)) - ! Write out the refractive indicies. - call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidx(nlwbands+1:))) - call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidx(nlwbands+1:))) - call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidx(:nlwbands))) - call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidx(:nlwbands))) + ! These fields control whether the particle is treated as a CCN. For now, + ! set these so that CARMA particles are not considered as CCN by the + ! CAM microphysics. + if (irhswell /= 0) then + count_text(1) = len('hygroscopic ') + call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic ' /)) + else + count_text(1) = len('insoluble ') + call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'insoluble ' /)) + end if + call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /)) + call wrap_put_var_realx(fid, slogvar, (/ 0._f /)) + call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, hygrovar, (/ 0._f /)) + call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /)) - ! Pad the names out with spaces. - aer_name = ' ' - aer_name(1:len(trim(c_name))) = c_name + ! Iterate over a range of relative humidities, since the particle may swell + ! with relative humidity which will change its optical properties. + do irh = 1, nrh - start_text(1) = 1 - count_text(1) = 32 - call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /)) - count_text(1) = 20 - call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /)) + ! Determine the wet radius. + call getwetr(carma, igroup, mie_rh(irh), r(ibin), rwet, rho(ibin), rhopwet, rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.') - ! These fields control whether the particle is treated as a CCN. For now, - ! set these so that CARMA particles are not considered as CCN by the - ! CAM microphysics. - if (irhswell /= 0) then - count_text(1) = len('hygroscopic ') - call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic ' /)) - else - count_text(1) = len('insoluble ') - call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'insoluble ' /)) - end if + ! Calculate at each wavelength. + do iwave = 1, NWAVE - call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /)) - call wrap_put_var_realx(fid, slogvar, (/ 0._f /)) - call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /)) - call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /)) - call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /)) - call wrap_put_var_realx(fid, hygrovar, (/ 0._f /)) - call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /)) - - ! Iterate over a range of relative humidities, since the particle may swell - ! with relative humidity which will change its optical properties. - do irh = 1, nrh - - ! Determine the wet radius. - call getwetr(carma, igroup, mie_rh(irh), r(ibin), rwet, rho(ibin), rhopwet, rc) - if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.') - - ! Calculate at each wavelength. - do iwave = 1, NWAVE -write(carma%f_LUNOPRT,*) "CARMA mie calc: start ", igroup, ibin, iwave, carma%f_wave(iwave), carma%f_group(igroup)%f_nmon(ibin) - - - ! Using Mie code, calculate the optical properties: extinction coefficient, - ! single scattering albedo and asymmetry factor. - ! Assume the particle is homogeneous (no core). - ! - ! NOTE: nmon, df, rmon and falpha are only used for fractal particles. - call mie(carma, & - carma%f_group(igroup)%f_imiertn, & - rwet, & - carma%f_wave(iwave), & - carma%f_group(igroup)%f_nmon(ibin), & - carma%f_group(igroup)%f_df(ibin), & - carma%f_group(igroup)%f_rmon, & - carma%f_group(igroup)%f_falpha, & - carma%f_group(igroup)%f_refidx(iwave), & - Qext, & - Qsca, & - asym, & - rc) - if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.') -write(carma%f_LUNOPRT,*) "CARMA mie calc: done ", Qext, Qsca, asym - - - ! Calculate the shortwave and longwave properties? - ! - ! NOTE: miess is in cgs units, but the optics file needs to be in mks - ! units, so perform the necessary conversions. - if (iwave <= nlwbands) then - - ! Longwave just needs absorption: abs_lw. - abs_lw(irh, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) - else - - ! Shortwave needs extinction, single scattering albedo and asymmetry factor: - ! ext_sw, ssa_sw and asm_sw. - ext_sw(irh, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) - ssa_sw(irh, iwave - nlwbands) = Qsca / Qext - asm_sw(irh, iwave - nlwbands) = asym - end if - end do - end do + ! Using Mie code, calculate the optical properties: extinction coefficient, + ! single scattering albedo and asymmetry factor. + ! Assume the particle is homogeneous (no core). + ! + ! NOTE: nmon, df, rmon and falpha are only used for fractal particles. + call mie(carma, & + carma%f_group(igroup)%f_imiertn, & + rwet, & + carma%f_wave(iwave), & + real(carma%f_group(igroup)%f_nmon(ibin),kind=f), & + carma%f_group(igroup)%f_df(ibin), & + carma%f_group(igroup)%f_rmon, & + carma%f_group(igroup)%f_falpha, & + refidx(iwave, 1), & + 0.0_f, & + refidx(iwave, 1), & + Qext, & + Qsca, & + asym, & + rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.') + + ! Calculate the shortwave and longwave properties? + ! + ! NOTE: miess is in cgs units, but the optics file needs to be in mks + ! units, so perform the necessary conversions. + if (iwave <= nlwbands) then - ! Write out the longwave fields. - ret = nf90_put_var (fid, abs_lw_var, abs_lw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', abs_lw_var - call handle_error (ret) - end if + ! Longwave just needs absorption: abs_lw. + abs_lw(irh, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + else - ! Write out the shortwave fields. - ret = nf90_put_var (fid, ext_sw_var, ext_sw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ext_sw_var - call handle_error (ret) - end if - ret = nf90_put_var (fid, ssa_sw_var, ssa_sw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ssa_sw_var - call handle_error (ret) + ! Shortwave needs extinction, single scattering albedo and asymmetry factor: + ! ext_sw, ssa_sw and asm_sw. + ext_sw(irh, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + ssa_sw(irh, iwave - nlwbands) = Qsca / Qext + asm_sw(irh, iwave - nlwbands) = asym end if - ret = nf90_put_var (fid, asm_sw_var, asm_sw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', asm_sw_var - call handle_error (ret) - end if - - ! Close the file. - call wrap_close(fid) - end if + end do end do + + ! Write out the longwave fields. + ret = nf90_put_var (fid, abs_lw_var, abs_lw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', abs_lw_var + call handle_error (ret) + end if + + ! Write out the shortwave fields. + ret = nf90_put_var (fid, ext_sw_var, ext_sw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ext_sw_var + call handle_error (ret) + end if + ret = nf90_put_var (fid, ssa_sw_var, ssa_sw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ssa_sw_var + call handle_error (ret) + end if + ret = nf90_put_var (fid, asm_sw_var, asm_sw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', asm_sw_var + call handle_error (ret) + end if + + ! Close the file. + call wrap_close(fid) end if end do return - end subroutine CARMA_CreateOpticsFile + end subroutine CARMA_CreateOpticsFile_Fixed - !! This routine creates a file containing a reference temperature profile - !! for use with fixed initialization. - subroutine CARMA_CreateRefTFile(carma, filepath, lev, reft, rc, refh2o, refh2so4) + + !! This routine creates files containing optical properties for the pure sulfate group + !! following Yu et al. (2015). These optical properties are used by the RRTMG radiation + !! code to include the impact of CARMA particles in the radiative transfer + !! calculation. + subroutine CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc) + use radconstants, only : nswbands, nlwbands use wrap_nf + use wetr, only : getwetr implicit none - type(carma_type), intent(inout) :: carma !! the carma object - character(len=*), intent(in) :: filepath !! the file path - real(kind=f), intent(in) :: lev(pver) !! pressure levels - real(kind=f), intent(in) :: reft(pver) !! reference temperature - integer, intent(out) :: rc !! return code, negative indicates failure - real(kind=f), optional, intent(in) :: refh2o(pver) !! reference water vapor - real(kind=f), optional, intent(in) :: refh2so4(pver) !! reference sulfuric acid + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group index + integer, intent(out) :: rc !! return code, negative indicates failure ! Local variables + integer :: ibin, iwave, iwtp + integer :: irhswell + integer :: imiertn + integer :: ienconc + real(kind=f) :: rho(NBIN), rhopwet + real(kind=f) :: r(NBIN), rmass(NBIN), rlow(NBIN), rup(NBIN) + real(kind=f) :: wave(NWAVE) + complex(kind=f) :: refidx(NWAVE) + complex(kind=f) :: refidxS(NWAVE, NREFIDX) + complex(kind=f) :: refidxW(NWAVE) + character(len=CARMA_NAME_LEN) :: name + character(len=CARMA_SHORT_NAME_LEN) :: shortname integer :: fid - integer :: levdim - integer :: levvar, tvar, h2ovar, h2so4var + integer :: rhdim, lwdim, swdim, wtpdim + integer :: rhvar, lwvar, swvar, wtp_var + integer :: rwetvar + integer :: abs_lw_wtp_var, qabs_lw_wtp_var + integer :: ext_sw_wtp_var, ssa_sw_wtp_var, asm_sw_wtp_var, qext_sw_wtp_var + integer :: omdim, andim, namedim + integer :: omvar, anvar, namevar integer :: dimids(2) + integer :: denvar, slogvar, dryrvar, rminvar, rmaxvar, hygrovar, ntmvar + real(kind=f) :: abs_lw_wtp(NMIE_WTP, nlwbands) + real(kind=f) :: qabs_lw_wtp(NMIE_WTP, nlwbands) + real(kind=f) :: ext_sw_wtp(NMIE_WTP, nswbands) + real(kind=f) :: qext_sw_wtp(NMIE_WTP, nswbands) + real(kind=f) :: ssa_sw_wtp(NMIE_WTP, nswbands) + real(kind=f) :: asm_sw_wtp(NMIE_WTP, nswbands) + character(len=8) :: c_name ! constituent name + character(len=32) :: aer_name ! long enough for both aername and name + character(len=255) :: filepath + real(kind=f) :: rwet + real(kind=f) :: Qext + real(kind=f) :: Qsca + real(kind=f) :: asym + integer :: start_text(2), count_text(2) + integer :: sw_r_refidx_var, sw_i_refidx_var, lw_r_refidx_var, lw_i_refidx_var + integer :: cnsttype ! constituent type + integer :: maxbin ! last prognostic bin + integer :: LUNOPRT ! logical unit number for output + logical :: do_print ! do print output? + integer :: ret + real(kind=f) :: volwater + real(kind=f) :: volsulfate + real(kind=f) :: volshell + integer :: igash2o ! Assume success. rc = 0 - ! Create the file. - call wrap_create(filepath, NF90_CLOBBER, fid) + ! Get the wavelength structure. + call CARMA_GET(carma, rc, wave=wave, do_print=do_print, LUNOPRT=LUNOPRT, igash2o=igash2o) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMA_Get failed.') + ! Get the necessary group properties. + call CARMAGROUP_Get(carma, igroup, rc, name=name, shortname=shortname, r=r, & + rlow=rlow, rup=rup, rmass=rmass, irhswell=irhswell, & + ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin, imiertn=imiertn) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') - ! Define the dimensions: lev - call wrap_def_dim(fid, 'lev', pver, levdim) + ! Get the necessary element properties. + call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho, refidx=refidxS) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.') - dimids(1) = levdim - call wrap_def_var(fid, 'lev', NF90_DOUBLE, 1, dimids(1:1), levvar) + ! Get the refractive index for water. + call CARMAGAS_Get(carma, igash2o, rc, refidx=refidxW) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGAS_Get failed.') - call wrap_put_att_text(fid, levvar, 'units', 'level') - call wrap_put_att_text(fid, levvar, 'long_name', 'hybrid level at midpoints (1000*(A+B))') - call wrap_put_att_text(fid, levvar, 'positive', 'down') - call wrap_put_att_text(fid, levvar, 'standard_name', 'atmosphere_hybrid_sigma_pressure_coordinate') - call wrap_put_att_text(fid, levvar, 'formula_terms', 'a: hyam b: hybm p0: P0 ps: PS') + ! A file needs to be created for each bin. + do ibin = 1, NBIN - ! Define the variables: T - call wrap_def_var(fid, 'T', NF90_DOUBLE, 1, dimids(1:1), tvar) + ! Bins past maxbin are treated as diagnostic even if the group + ! is prognostic and thus are not advected in the paerent model. + if (ibin <= maxbin) then - call wrap_put_att_text(fid, tvar, 'units', 'K') - call wrap_put_att_text(fid, tvar, 'long_name', 'Temperature') + write(c_name, '(A, I2.2)') trim(shortname), ibin - if ((carma%f_igash2o /= 0) .and. present(refh2o)) then - call wrap_def_var(fid, 'Q', NF90_DOUBLE, 1, dimids(1:1), h2ovar) + ! Construct the path to the file. Each model will have its own subdirectory + ! where the optical property files are stored. + filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc' + + if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath) - call wrap_put_att_text(fid, h2ovar, 'units', 'kg/kg') - call wrap_put_att_text(fid, h2ovar, 'long_name', 'Specific Humidity') - end if + ! Create the file. + call wrap_create(filepath, NF90_CLOBBER, fid) + + ! Define the dimensions: rh, lwbands, swbands + call wrap_def_dim(fid, 'rh_idx', NMIE_RH, rhdim) + call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim) + call wrap_def_dim(fid, 'sw_band', nswbands, swdim) + + call wrap_def_dim(fid, 'wgtpct', NMIE_WTP, wtpdim) + + dimids(1) = rhdim + call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1), rhvar) + call wrap_def_var(fid, 'rwet',NF90_DOUBLE, 1, dimids(1), rwetvar) + + dimids(1) = lwdim + call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1), lwvar) + + dimids(1) = swdim + call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1), swvar) + + dimids(1) = wtpdim + call wrap_def_var(fid, 'wgtpct', NF90_DOUBLE, 1, dimids(1), wtp_var) + + call wrap_put_att_text(fid, rhvar, 'units', 'fraction') + call wrap_put_att_text(fid, rwetvar, 'units', 'cm') + call wrap_put_att_text(fid, lwvar, 'units', 'm') + call wrap_put_att_text(fid, swvar, 'units', 'm') + + call wrap_put_att_text(fid, wtp_var,'units', 'unitless') + call wrap_put_att_text(fid, wtp_var,'long_name', 'weight percent') + + call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity') + call wrap_put_att_text(fid, rwetvar, 'long_name', 'wet radius') + call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands') + call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands') + + ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw + ! Define 2-dimension (:nrh,:nswbands) LW optics properties: abs_lw, qabs_lw + dimids(1) = wtpdim + dimids(2) = lwdim + call wrap_def_var(fid, 'abs_lw_wtp', NF90_DOUBLE, 2, dimids(1:2), abs_lw_wtp_var) + call wrap_def_var(fid, 'qabs_lw_wtp',NF90_DOUBLE, 2, dimids(1:2), qabs_lw_wtp_var) + + call wrap_put_att_text(fid, abs_lw_wtp_var, 'units', 'meter^2 kilogram^-1') + call wrap_put_att_text(fid, qabs_lw_wtp_var,'units', '-') + + ! Define 2-dimension (:nrh,:nswbands) optics properties: ext_sw, qext_sw, ssa_sw, asm_sw + dimids(1) = wtpdim + dimids(2) = swdim + call wrap_def_var(fid, 'ext_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), ext_sw_wtp_var) + call wrap_def_var(fid, 'qext_sw_wtp',NF90_DOUBLE, 2, dimids(1:2), qext_sw_wtp_var) + call wrap_def_var(fid, 'ssa_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), ssa_sw_wtp_var) + call wrap_def_var(fid, 'asm_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), asm_sw_wtp_var) + + call wrap_put_att_text(fid, ssa_sw_wtp_var, 'units', 'fraction') + call wrap_put_att_text(fid, qext_sw_wtp_var,'units', '-') + call wrap_put_att_text(fid, ext_sw_wtp_var, 'units', 'meter^2 kilogram^-1') + call wrap_put_att_text(fid, asm_sw_wtp_var, 'units', '-') + + ! Define the variables for the refractive indicies. + dimids(1) = swdim + call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1), sw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1), sw_i_refidx_var) + + dimids(1) = lwdim + call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1), lw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1), lw_i_refidx_var) + + call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-') + + call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave') + call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave') + + + ! Define fields that define the aerosol properties. + call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim) + dimids(1) = omdim + call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1), omvar) + + call wrap_def_dim(fid, 'namelength', 20, andim) + dimids(1) = andim + call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1), anvar) + + call wrap_def_dim(fid, 'name_len', 32, namedim) + dimids(1) = namedim + call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids, namevar) + + call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1), denvar) + call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1), slogvar) + call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1), dryrvar) + call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1), rminvar) + call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1), rmaxvar) + call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1), hygrovar) + call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1), ntmvar) + + call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3') + call wrap_put_att_text(fid, slogvar, 'units', '-') + call wrap_put_att_text(fid, dryrvar, 'units', 'm') + call wrap_put_att_text(fid, rminvar, 'units', 'm') + call wrap_put_att_text(fid, rmaxvar, 'units', 'm') + call wrap_put_att_text(fid, hygrovar, 'units', '-') + call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1') + + call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density') + call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol') + call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol') + call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin') + call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin') + call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol') + call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol') + + ! End the defintion phase of the netcdf file. + call wrap_enddef(fid) + + ! Write out the dimensions. + call wrap_put_var_realx(fid, rhvar, mie_rh(:)) + call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f) + call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f) + + call wrap_put_var_realx(fid, wtp_var, mie_wtp(:)*100._f) + + ! Write out the refractive indicies. + call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidxS(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidxS(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidxS(:nlwbands, 1))) + call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidxS(:nlwbands, 1))) + + ! Pad the names out with spaces. + aer_name = ' ' + aer_name(1:len(trim(c_name))) = c_name + + start_text(1) = 1 + count_text(1) = 32 + call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /)) + count_text(1) = 20 + call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /)) + + count_text(1) = len('hygroscopic_wtp ') + call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic_wtp ' /)) + + call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /)) + call wrap_put_var_realx(fid, slogvar, (/ 0._f /)) + call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, hygrovar, (/ 0.6_f /)) + call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /)) + + ! For now, ext_sw(:nrh, :nswbands) and ext_sw_coreshell(:nrh, :nswbands, :ncoreshellratio) both are calculated + ! Since other aerosols in CAM may use ext_sw rather than ext_sw_coreshell + ! Modified by Pengfei Yu + ! April.1, 2012 + + ! calculate qext and ext for pure sulfate dependent on weight percent + ! ideally qext is based on (wgt,temp,wave), however Beyer et al. (1996) Figure 5 + ! shows sulfate density is roughly 0.006 g/cm3/k, I negelet temp dimension, assuming temp = 270 K + ! In code, sulfate density is precisely calculated to determine wet raidus + do iwtp = 1, NMIE_WTP + + ! NOTE: Weight percent is normal a result of the getwetr calculation. To build the + ! table based upon weight percent, we need to pass in the desired value and a + ! reference temperature. In that case, the RH is ignored. + call getwetr(carma, igroup, mie_rh(1), r(ibin), rwet, rho(ibin), rhopwet, rc, wgtpct=mie_wtp(iwtp)*100._f, temp=270._f) + if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.') + + ! This is not in Yu (2015), but rather than using the refractive + ! index of H2SO4 for the shell, do a volume mix of water and H2SO4 + ! for the refractive index of the shell. + volwater = rwet**3._f - r(ibin)**3._f + volsulfate = r(ibin)**3._f + volshell = volwater + volsulfate + if (volshell > 0._f) then + refidx(:) = (volwater / volshell) * refidxW(:) + (volsulfate / volshell) * refidxS(:, 1) + else + refidx(:) = refidxS(:, 1) + end if - if ((carma%f_igash2so4 /= 0) .and. present(refh2so4)) then - call wrap_def_var(fid, 'H2SO4', NF90_DOUBLE, 1, dimids(1:1), h2so4var) + ! Calculate at each wavelength. + do iwave = 1, NWAVE - call wrap_put_att_text(fid, h2so4var, 'units', 'kg/kg') - call wrap_put_att_text(fid, h2so4var, 'long_name', 'H2SO4') - end if + ! Using Mie code, calculate the optical properties: extinction coefficient, + ! single scattering albedo and asymmetry factor. + ! Assume the particle is homogeneous (no core). + ! + ! NOTE: The refractive index for sulfate changes with RH/weight percent, which + ! is not reflected in this code. + call mie(carma, & + imiertn, & + rwet, & + wave(iwave), & + 0._f, & + 3.0_f, & + 0.0_f, & + 1.0_f, & + refidx(iwave), & + 0.0_f, & + refidx(iwave), & + Qext, & + Qsca, & + asym, & + rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.') + + ! Calculate the shortwave and longwave properties? + ! + ! NOTE: miess is in cgs units, but the optics file needs to be in mks + ! units, so perform the necessary conversions. + if (iwave <= nlwbands) then - ! End the defintion phase of the netcdf file. - call wrap_enddef(fid) + ! Longwave just needs absorption: abs_lw. + qabs_lw_wtp(iwtp, iwave) = (Qext - Qsca) ! absorption per particle + abs_lw_wtp (iwtp, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + else + ! Shortwave needs extinction, single scattering albedo and asymmetry factor: + ! ext_sw, ssa_sw and asm_sw. + qext_sw_wtp(iwtp, iwave - nlwbands) = Qext ! extinction per particle + ext_sw_wtp (iwtp, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + ssa_sw_wtp (iwtp, iwave - nlwbands) = Qsca / Qext + asm_sw_wtp (iwtp, iwave - nlwbands) = asym + end if + end do ! iwave + end do ! iwtp + + ! Write out the longwave fields. + ret = nf90_put_var(fid, abs_lw_wtp_var, abs_lw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', fid, abs_lw_wtp_var + call handle_error(ret) + end if - ! Write out the dimensions. - call wrap_put_var_realx(fid, levvar, lev) + ret = nf90_put_var(fid, qabs_lw_wtp_var, qabs_lw_wtp(:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', qabs_lw_wtp_var + call handle_error(ret) + end if - ! Write out the variables. - call wrap_put_var_realx(fid, tvar, reft) + ! Write out the shortwave fields. + ret = nf90_put_var(fid, ext_sw_wtp_var, ext_sw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', ext_sw_wtp_var + call handle_error(ret) + end if - if ((carma%f_igash2o /= 0) .and. present(refh2o)) then - call wrap_put_var_realx(fid, h2ovar, refh2o(:)) - end if + ret = nf90_put_var(fid, qext_sw_wtp_var,qext_sw_wtp(:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', qext_sw_wtp_var + call handle_error(ret) + end if - if ((carma%f_igash2so4 /= 0) .and. present(refh2so4)) then - call wrap_put_var_realx(fid, h2so4var, refh2so4(:)) - end if + ret = nf90_put_var(fid, ssa_sw_wtp_var, ssa_sw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', ssa_sw_wtp_var + call handle_error(ret) + end if + + ret = nf90_put_var(fid, asm_sw_wtp_var, asm_sw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', asm_sw_wtp_var + call handle_error(ret) + end if - ! Close the file. - call wrap_close(fid) + ! Close the file. + call wrap_close(fid) + end if + end do return - end subroutine CARMA_CreateRefTFile + end subroutine CARMA_CreateOpticsFile_Sulfate !! Calculate the aerodynamic resistance for dry deposition. @@ -2645,4 +3021,87 @@ subroutine CARMA_calcram(ustar, z0, pdel, pmid, tmid, obklen, ram) return end subroutine CARMA_calcram + + !--------------------------------------------------------------------------- + ! define fields for reference profiles in cam restart file + !--------------------------------------------------------------------------- + subroutine CARMA_restart_init( File ) + use cam_pio_utils, only: cam_pio_def_dim + use pio, only: file_desc_t, pio_def_var, pio_double + + ! arguments + type(file_desc_t),intent(inout) :: File ! pio File pointer + + ! local variables + integer :: levid, ierr + + if (carma_do_fixedinit) then + call cam_pio_def_dim(File, 'lev', pver, levid, existOK=.true.) + ierr = pio_def_var(File, 'CARMA_REF_T', pio_double, (/ levid /), t_ref_desc) + ierr = pio_def_var(File, 'CARMA_REF_H2O', pio_double, (/ levid /), h2o_ref_desc) + ierr = pio_def_var(File, 'CARMA_REF_H2SO4', pio_double, (/ levid /), h2so4_ref_desc) + endif + + end subroutine CARMA_restart_init + + !--------------------------------------------------------------------------- + ! write reference profiles to restart file + !--------------------------------------------------------------------------- + subroutine CARMA_restart_write(File) + use pio, only: file_desc_t, pio_put_var + + ! arguments + type(file_desc_t), intent(inout) :: File + + ! local variables + integer ::ierr + + if (carma_do_fixedinit) then + ierr = pio_put_var(File, t_ref_desc, carma_t_ref) + if (carma%f_igash2o /= 0) then + ierr = pio_put_var(File, h2o_ref_desc, carma_h2o_ref) + endif + if (carma%f_igash2So4 /= 0) then + ierr = pio_put_var(File, h2so4_ref_desc, carma_h2so4_ref) + endif + endif + + end subroutine CARMA_restart_write + + !--------------------------------------------------------------------------- + ! read reference profiles from restart file + !--------------------------------------------------------------------------- + subroutine CARMA_restart_read(File) + use pio, only: file_desc_t, pio_inq_varid, pio_get_var + + ! arguments + type(file_desc_t),intent(inout) :: File ! pio File pointer + + ! local variables + integer :: ierr, varid + character(len=*), parameter :: subname = 'CARMA_restart_read: ' + + if (carma_do_fixedinit) then + ierr = pio_inq_varid(File, 'CARMA_REF_T', varid) + if (varid>0) then + ierr = pio_get_var(File, varid, carma_t_ref) + else + call endrun(subname//'restart file must include CARMA_REF_T') + endif + ierr = pio_inq_varid(File, 'CARMA_REF_H2O', varid) + if (varid>0) then + ierr = pio_get_var(File, varid, carma_h2o_ref) + else if (carma%f_igash2o /= 0) then + call endrun(subname//'restart file must include CARMA_REF_H2O') + endif + ierr = pio_inq_varid(File, 'CARMA_REF_H2SO4', varid) + if (varid>0) then + ierr = pio_get_var(File, varid, carma_h2so4_ref) + else if (carma%f_igash2So4 /= 0) then + call endrun(subname//'restart file must include CARMA_REF_H2SO4') + endif + endif + + end subroutine CARMA_restart_read + end module carma_intr diff --git a/src/physics/carma/cam/carma_precision_mod.F90 b/src/physics/carma/cam/carma_precision_mod.F90 index db76f798c6..ae22471312 100644 --- a/src/physics/carma/cam/carma_precision_mod.F90 +++ b/src/physics/carma/cam/carma_precision_mod.F90 @@ -35,4 +35,4 @@ module carma_precision_mod !! Define smallest possible number such that ONE + ALMOST_ZERO > ONE real(kind=f), parameter :: ALMOST_ZERO = epsilon( ONE ) real(kind=f), parameter :: ALMOST_ONE = ONE - ALMOST_ZERO -end module +end module carma_precision_mod diff --git a/src/physics/carma/models/bc_strat/carma_model_mod.F90 b/src/physics/carma/models/bc_strat/carma_model_mod.F90 index 42dc276a01..e4a933dd67 100644 --- a/src/physics/carma/models/bc_strat/carma_model_mod.F90 +++ b/src/physics/carma/models/bc_strat/carma_model_mod.F90 @@ -417,4 +417,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/src/physics/carma/models/cirrus/carma_model_mod.F90 b/src/physics/carma/models/cirrus/carma_model_mod.F90 index 446a17cdd8..b751221964 100644 --- a/src/physics/carma/models/cirrus/carma_model_mod.F90 +++ b/src/physics/carma/models/cirrus/carma_model_mod.F90 @@ -315,7 +315,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -1344,7 +1344,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. sub_d = 2._f * (r(NBIN) + (dr(NBIN) / 2._f)) * shapeFactor - sub_dd = (snow_max_d * 1e-4 - sub_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - sub_d) / NINTS_SNOW sub_d = sub_d + sub_dd / 2._f remainder = 0._f @@ -1361,7 +1361,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! m = aD^2.1 ! ! NOTE: This needs to match the density assumption made in the detrained ice bins. - remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1) + remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1_r8) sub_d = sub_d + sub_dd end do @@ -1374,7 +1374,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. snow_d = 2._f * ((r(NBIN) + dr(NBIN) / 2._f)) - sub_dd = (snow_max_d * 1e-4 - snow_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - snow_d) / NINTS_SNOW sub_d = snow_d + (sub_dd / 2._f) snow_r3 = 0._f @@ -2064,4 +2064,4 @@ subroutine CARMA_CheckMassAndEnergy(carma, cstate, madeSnow, name, state, & return end subroutine CARMA_CheckMassAndEnergy -end module +end module carma_model_mod diff --git a/src/physics/carma/models/cirrus/growevapl.F90 b/src/physics/carma/models/cirrus/growevapl.F90 index e1020eb802..c6659bdbb4 100644 --- a/src/physics/carma/models/cirrus/growevapl.F90 +++ b/src/physics/carma/models/cirrus/growevapl.F90 @@ -216,7 +216,7 @@ subroutine growevapl(carma, cstate, iz, rc) if( x .lt. 1._f )then growlg(ibin,igroup) = dmdt(ibin)/pc(iz,ibin,iepart) & - * ( ar(ibin) - 0.5*dela(ibin)*x + & + * ( ar(ibin) - 0.5_r8*dela(ibin)*x + & (x/2._f - x**2/3._f)*a6(ibin) ) else growlg(ibin,igroup) = dmdt(ibin) / dm(ibin,igroup) diff --git a/src/physics/carma/models/cirrus_dust/carma_mod.F90 b/src/physics/carma/models/cirrus_dust/carma_mod.F90 index ab89065690..f6ac6945ae 100644 --- a/src/physics/carma/models/cirrus_dust/carma_mod.F90 +++ b/src/physics/carma/models/cirrus_dust/carma_mod.F90 @@ -1475,4 +1475,4 @@ subroutine CARMA_Get(carma, rc, LUNOPRT, NBIN, NELEM, NGAS, NGROUP, NSOLUTE, NWA return end subroutine CARMA_Get -end module +end module carma_mod diff --git a/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 b/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 index 036e1ea977..0ff512539e 100644 --- a/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 +++ b/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 @@ -335,7 +335,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -1386,7 +1386,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. sub_d = 2._f * (r(NBIN) + (dr(NBIN) / 2._f)) * shapeFactor - sub_dd = (snow_max_d * 1e-4 - sub_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - sub_d) / NINTS_SNOW sub_d = sub_d + sub_dd / 2._f remainder = 0._f @@ -1403,7 +1403,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! m = aD^2.1 ! ! NOTE: This needs to match the density assumption made in the detrained ice bins. - remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1) + remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1_r8) sub_d = sub_d + sub_dd end do @@ -1416,7 +1416,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. snow_d = 2._f * ((r(NBIN) + dr(NBIN) / 2._f)) - sub_dd = (snow_max_d * 1e-4 - snow_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - snow_d) / NINTS_SNOW sub_d = snow_d + (sub_dd / 2._f) snow_r3 = 0._f @@ -2570,7 +2570,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ilat, ilon, ielem, igroup, ibin * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/(r(ibin)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*(r(ibin)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) else - uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2./rhoa) & + uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2._r8/rhoa) & * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/((.75e-4_r8)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*((.75e-4_r8)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) endif @@ -2703,7 +2703,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) if (present(wbk)) then k = wbk else - k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR + k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR ! k = 2.5_r8 ! Lansing's estimate end if @@ -2718,4 +2718,4 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) end subroutine WeibullWind -end module +end module carma_model_mod diff --git a/src/physics/carma/models/cirrus_dust/growevapl.F90 b/src/physics/carma/models/cirrus_dust/growevapl.F90 index e1020eb802..c6659bdbb4 100644 --- a/src/physics/carma/models/cirrus_dust/growevapl.F90 +++ b/src/physics/carma/models/cirrus_dust/growevapl.F90 @@ -216,7 +216,7 @@ subroutine growevapl(carma, cstate, iz, rc) if( x .lt. 1._f )then growlg(ibin,igroup) = dmdt(ibin)/pc(iz,ibin,iepart) & - * ( ar(ibin) - 0.5*dela(ibin)*x + & + * ( ar(ibin) - 0.5_r8*dela(ibin)*x + & (x/2._f - x**2/3._f)*a6(ibin) ) else growlg(ibin,igroup) = dmdt(ibin) / dm(ibin,igroup) diff --git a/src/physics/carma/models/dust/carma_model_mod.F90 b/src/physics/carma/models/dust/carma_model_mod.F90 index 22ba9b69d2..09c96b2bf0 100644 --- a/src/physics/carma/models/dust/carma_model_mod.F90 +++ b/src/physics/carma/models/dust/carma_model_mod.F90 @@ -46,14 +46,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -66,6 +71,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -90,7 +99,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -107,7 +116,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Report model specific namelist configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_DefineModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.") if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -122,7 +131,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, 1, "dust", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="CRDUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -130,7 +139,7 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -143,7 +152,7 @@ subroutine CARMA_DefineModel(carma, rc) return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -153,7 +162,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -178,14 +187,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -211,14 +220,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -249,7 +258,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -258,7 +267,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Lin Su, Pengfei Yu, Chuck Bardeen !! @version Dec-2010 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -276,10 +285,9 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure - integer :: ilat(pcols) ! latitude index - integer :: ilon(pcols) ! longitude index integer :: lchnk ! chunk identifier integer :: ncol ! number of columns in chunk integer :: icol ! column index @@ -341,7 +349,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend ! Process each column. do icol = 1,ncol - call CARMA_SurfaceWind(carma, state, icol, ielem, igroup, idustbin, cam_in, uv10, wwd, uth, rc) + call CARMAMODEL_SurfaceWind(carma, state, icol, ielem, igroup, idustbin, cam_in, uv10, wwd, uth, rc) ! Is the wind above the threshold for dust production? if (uv10 > uth) then @@ -351,16 +359,15 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend ! Scale the clay bins based upon the smallest silt bin. surfaceFlux(icol) = clay_mf(ibin) * surfaceFlux(icol) - end do ! For debug purposes, output the soil erosion factor. call outfld('CRSLERFC', soil_factor(:ncol, lchnk), ncol, lchnk) - end if + end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -368,16 +375,17 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use cam_history, only: addfld, add_default, horiz_only use constituents, only: pcnst implicit none - type(carma_type), intent(in) :: carma !! the carma object - logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent + type(carma_type), intent(in) :: carma !! the carma object + logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency - integer, intent(out) :: rc !! return code, negative indicates failure + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + integer, intent(out) :: rc !! return code, negative indicates failure ! -------- local variables ---------- integer :: ibin ! CARMA bin index @@ -421,7 +429,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do ! Read in the soil factors. - call CARMA_ReadSoilErosionFactor(carma, rc) + call CARMAMODEL_ReadSoilErosionFactor(carma, rc) if (RC < RC_ERROR) return ! To determine Clay Mass Fraction @@ -431,7 +439,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) if (RC < RC_ERROR) return if (shortname .eq. "CRDUST") then - call CARMA_ClayMassFraction(carma, igroup, rc) + call CARMAMODEL_ClayMassFraction(carma, igroup, rc) end if end do @@ -452,7 +460,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call addfld('CRSLERFC', horiz_only, 'A', 'fraction', 'CARMA soil erosion factor') return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -464,7 +472,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -487,15 +495,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -514,7 +562,7 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition !! Determines the mass fraction for the clay (submicron) bins based upon @@ -529,7 +577,7 @@ end subroutine CARMA_WetDeposition !! !! @version July-2012 !! @author Lin Su, Pengfei Yu, Chuck Bardeen - subroutine CARMA_ClayMassFraction(carma, igroup, rc) + subroutine CARMAMODEL_ClayMassFraction(carma, igroup, rc) implicit none type(carma_type), intent(in) :: carma !! the carma object @@ -610,7 +658,7 @@ subroutine CARMA_ClayMassFraction(carma, igroup, rc) clay_mf(ind_low(IABOVE):) = 1._r8 return - end subroutine CARMA_ClayMassFraction + end subroutine CARMAMODEL_ClayMassFraction !! Calculate the sea surface wind with a Weibull distribution. @@ -621,7 +669,7 @@ end subroutine CARMA_ClayMassFraction !! !! @author Lin Su, Pengfei Yu, Chuck Bardeen !! @version July-2012 - subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv10, wwd, uth, rc) + subroutine CARMAMODEL_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv10, wwd, uth, rc) use ppgrid, only: pcols, pver use physics_types, only: physics_state use camsrfexch, only: cam_in_t @@ -669,7 +717,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/(r(ibin)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*(r(ibin)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) else - uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2./rhoa) & + uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2._r8/rhoa) & * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/((.75e-4_r8)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*((.75e-4_r8)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) endif @@ -681,7 +729,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv call WeibullWind(uv10, uth, 2._r8, wwd) return - end subroutine CARMA_SurfaceWind + end subroutine CARMAMODEL_SurfaceWind !! Read in the dust source (soil) erodibility factor from a NETCDF file. In this @@ -693,7 +741,7 @@ end subroutine CARMA_SurfaceWind !! !! @author Pengfei Yu !! @version July-2012 - subroutine CARMA_ReadSoilErosionFactor(carma, rc) + subroutine CARMAMODEL_ReadSoilErosionFactor(carma, rc) use ppgrid, only: begchunk, endchunk, pcols use ioFileMod, only: getfil use wrap_nf @@ -742,7 +790,7 @@ subroutine CARMA_ReadSoilErosionFactor(carma, rc) call wrap_inq_varid(fid, 'new_source', idvar) i = nf90_get_var (fid, idvar, ero_factor) if (i/=NF90_NOERR) then - write(iulog,*)'CARMA_ReadSoilErosionFactor: error reading varid =', idvar + write(iulog,*)'CARMAMODEL_ReadSoilErosionFactor: error reading varid =', idvar call handle_error (i) end if call wrap_inq_varid(fid, 'plat', idlat) @@ -775,7 +823,8 @@ subroutine CARMA_ReadSoilErosionFactor(carma, rc) deallocate(ero_lon) deallocate(ero_factor) - end subroutine CARMA_ReadSoilErosionFactor + return + end subroutine CARMAMODEL_ReadSoilErosionFactor !! Calculate the nth mean of u using Weibull wind distribution @@ -804,7 +853,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) if (present(wbk)) then k = wbk else - k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR + k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR ! k = 2.5_r8 ! Lansing's estimate end if @@ -819,4 +868,92 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) end subroutine WeibullWind -end module + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics + +end module carma_model_mod diff --git a/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 b/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 index 360ddb9499..efe43af66d 100644 --- a/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 +++ b/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 @@ -24,16 +24,16 @@ module carma_model_flags_mod ! ! Create a public definition of any new namelist variables that you wish to have, ! and default them to an inital value. - real(r8), public :: carma_emis_dust = 0._r8 !! Total dust emission for the event (kg) - real(r8), public :: carma_emis_soot = 0._r8 !! Total soot emission for the event (kg) - integer, public :: carma_emis_startdate = 1 !! start year and day of year (yyyyddd) - integer, public :: carma_emis_stopdate = 1 !! stop year and day of year (yyyyddd) - integer, public :: carma_emis_starttime = 0 !! start time of day (s) - integer, public :: carma_emis_stoptime = 0 !! stop time of day (s) - real(r8), public :: carma_emis_minlat = -90. !! minimum latitude - real(r8), public :: carma_emis_maxlat = 90. !! maximum latitude - real(r8), public :: carma_emis_minlon = 0. !! minimum longitude - real(r8), public :: carma_emis_maxlon = 360. !! maximum longitude + real(r8), public :: carma_emis_dust = 0._r8 !! Total dust emission for the event (kg) + real(r8), public :: carma_emis_soot = 0._r8 !! Total soot emission for the event (kg) + integer, public :: carma_emis_startdate = 1 !! start year and day of year (yyyyddd) + integer, public :: carma_emis_stopdate = 1 !! stop year and day of year (yyyyddd) + integer, public :: carma_emis_starttime = 0 !! start time of day (s) + integer, public :: carma_emis_stoptime = 0 !! stop time of day (s) + real(r8), public :: carma_emis_minlat = -90._r8 !! minimum latitude + real(r8), public :: carma_emis_maxlat = 90._r8 !! maximum latitude + real(r8), public :: carma_emis_minlon = 0._r8 !! minimum longitude + real(r8), public :: carma_emis_maxlon = 360._r8 !! maximum longitude logical, public :: carma_fractal_soot = .false. !! fractal Soot contains diff --git a/src/physics/carma/models/meteor_impact/carma_model_mod.F90 b/src/physics/carma/models/meteor_impact/carma_model_mod.F90 index f8ebec713d..ecc131f0cf 100755 --- a/src/physics/carma/models/meteor_impact/carma_model_mod.F90 +++ b/src/physics/carma/models/meteor_impact/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -65,6 +70,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) = (/ 0._f, 0.5_f, 0.7_f, 0.8_f, 0.9_f, 0.95_f, 0.98_f, 0.99_f /) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -96,7 +105,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -107,7 +116,7 @@ subroutine CARMA_DefineModel(carma, rc) real(kind=f), parameter :: dust_vmrat = 2.49_f ! dust volume ratio real(kind=f), parameter :: soot_rmin = 20.e-7_f ! dust minimum radius (cm) real(kind=f), parameter :: soot_vmrat = 2.49_f ! dust volume ratio - complex(kind=f) :: refidx(NWAVE) ! refractice indices + complex(kind=f) :: refidx(NWAVE,NREFIDX) ! refractice indices integer :: LUNOPRT ! logical unit number for output logical :: do_print ! do print output? @@ -123,13 +132,13 @@ subroutine CARMA_DefineModel(carma, rc) if (carma_emis_maxlon < 0._f) carma_emis_maxlon = 360._f + carma_emis_maxlon if (carma_emis_minlat > carma_emis_maxlat) then - if (do_print) write(LUNOPRT,*) 'CARMA_DefineModel::ERROR - carma_emis_minlat greater than carma_emis_maxlat' + if (do_print) write(LUNOPRT,*) 'CARMAMODEL_DefineModel::ERROR - carma_emis_minlat greater than carma_emis_maxlat' end if ! Report model specific namelist configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.") if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -154,19 +163,10 @@ subroutine CARMA_DefineModel(carma, rc) ! defined. If wetdep is defined, then the optional solubility factor ! should also be defined. - ! Use the same refractive index at all wavelengths. This value is typical of soot and - ! is recommended by Toon et al. 2012. TBD Wagner et al. 2011 shows variability in the - ! real part (0.003 (IR) to 0.05 (UV)). - refidx(:) = (1.53_f, 0.008_f) - call CARMAGROUP_Create(carma, I_GRP_DUST, "Dust", dust_rmin, dust_vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & - scavcoef=0.1_f, shortname="CRDUST", refidx=refidx, do_mie=.true.) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') - - ! Use the same refractive index at all wavelengths. This value is typical of soot and - ! is recommended by Toon et al. 2012. - refidx(:) = (1.8_f, 0.67_f) + scavcoef=0.1_f, shortname="CRDUST", do_mie=.true.) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') if (carma_fractal_soot) then RHO_SOOT = 1.8_f @@ -178,27 +178,37 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_SOOT, "Soot", soot_rmin, soot_vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.1_f, & - scavcoef=0.1_f, shortname="CRSOOT", refidx=refidx, do_mie=.true., & + scavcoef=0.1_f, shortname="CRSOOT", do_mie=.true., & is_fractal=.true., rmon=soot_rmon, df=soot_df, falpha=soot_falpha, & imiertn=I_MIERTN_BOTET1997) else RHO_SOOT = 1.0_f call CARMAGROUP_Create(carma, I_GRP_SOOT, "Soot", soot_rmin, soot_vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.1_f, & - scavcoef=0.1_f, shortname="CRSOOT", refidx=refidx, do_mie=.true.) + scavcoef=0.1_f, shortname="CRSOOT", do_mie=.true.) end if - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements ! ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. - call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') - call CARMAELEMENT_Create(carma, I_ELEM_SOOT, I_GRP_SOOT, "Soot", RHO_SOOT, I_INVOLATILE, I_SOOT, rc, shortname="CRSOOT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + ! Use the same refractive index at all wavelengths. This value is typical of dust and + ! is recommended by Toon et al. 2012. TBD Wagner et al. 2011 shows variability in the + ! real part (0.003 (IR) to 0.05 (UV)). + refidx(:,1) = CMPLX(1.53_f, 0.008_f, kind=f) + + call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST", refidx=refidx) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') + + ! Use the same refractive index at all wavelengths. This value is typical of soot and + ! is recommended by Toon et al. 2012. + refidx(:,1) = CMPLX(1.8_f, 0.67_f, kind=f) + + call CARMAELEMENT_Create(carma, I_ELEM_SOOT, I_GRP_SOOT, "Soot", RHO_SOOT, I_INVOLATILE, I_SOOT, rc, shortname="CRSOOT", refidx=refidx) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -209,13 +219,13 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') call CARMA_AddCoagulation(carma, I_GRP_SOOT, I_GRP_SOOT, I_GRP_SOOT, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -225,7 +235,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -250,14 +260,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -283,14 +293,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -329,7 +339,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, do ibin = 1, NBIN call CARMASTATE_GetBin(cstate, ielem, ibin, mmr, rc, sedimentationFlux=sflx) - if (rc < 0) call endrun('CARMA_DiagnoseBulk::CARMA_GetBin failed.') + if (rc < 0) call endrun('CARMAMODEL_DiagnoseBulk::CARMA_GetBin failed.') cam_out%bcphidry(icol) = cam_out%bcphidry(icol) + max(sflx, 0._r8) end do @@ -338,7 +348,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, do ibin = 1, NBIN call CARMASTATE_GetBin(cstate, ielem, ibin, mmr, rc, sedimentationFlux=sflx) - if (rc < 0) call endrun('CARMA_DiagnoseBulk::CARMA_GetBin failed.') + if (rc < 0) call endrun('CARMAMODEL_DiagnoseBulk::CARMA_GetBin failed.') if (carma_dustmap(ibin) == 1) then cam_out%dstdry1(icol) = cam_out%dstdry1(icol) + max(sflx, 0._r8) @@ -352,7 +362,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end do return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -361,7 +371,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -382,6 +392,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure real(r8), parameter :: mu_dust_gnd = 1._r8 ! width parameter, dust, ground (km) @@ -563,7 +574,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -574,7 +585,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only: pcnst use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_area_all_p, get_ncols_p use shr_reprosum_mod, only: shr_reprosum_calc @@ -586,14 +597,15 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! NOTE: The dust distribution has not been specified yet, but it should be different ! from the soot. - real(kind=f), parameter :: rm_dust = 0.11 ! dust mean radius (um) - real(kind=f), parameter :: sigma_dust = 1.6 ! dust variance - real(kind=f), parameter :: rm_soot = 0.11 ! soot mean radius (um) - real(kind=f), parameter :: sigma_soot = 1.6 ! soot variance + real(kind=f), parameter :: rm_dust = 0.11_r8 ! dust mean radius (um) + real(kind=f), parameter :: sigma_dust = 1.6_r8 ! dust variance + real(kind=f), parameter :: rm_soot = 0.11_r8 ! soot mean radius (um) + real(kind=f), parameter :: sigma_soot = 1.6_r8 ! soot variance integer :: i real(kind=f) :: r(NBIN) @@ -735,7 +747,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end if return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -747,7 +759,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -767,15 +779,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! Add initial condition here. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -817,6 +869,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) end if return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 b/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 index 0b6d83aba1..4ec2910f44 100644 --- a/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 +++ b/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -62,6 +67,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -102,7 +111,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -120,7 +129,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Report model specific namelist configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.") if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -139,7 +148,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_DUST, "meteor smoke", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -148,7 +157,7 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, & I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -159,10 +168,10 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -172,7 +181,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -197,14 +206,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -230,14 +239,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -268,7 +277,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -277,7 +286,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version Jan-2011 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -296,6 +305,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilat ! latitude index @@ -435,7 +445,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -481,7 +491,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -489,7 +499,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use ioFileMod, only: getfil use constituents, only: pcnst use wrap_nf @@ -499,6 +509,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilev ! level index @@ -524,7 +535,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.") ! Initialize the emissions rate table. if (carma_do_emission) then @@ -565,7 +576,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -573,7 +584,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -642,7 +653,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! There should be one time for each day of the year, so ! quit if it isn't correct. if (carma_escale_nTimes .ne. 365) then - call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") + call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") endif call wrap_inq_dimid(fid, "ltime", ltime_did) @@ -665,7 +676,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call wrap_inq_varid(fid, 'SGRF', grf_vid) tmp = nf90_get_var (fid, grf_vid, carma_escale_grf) if (tmp/=NF90_NOERR) then - write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid + write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid call handle_error (tmp) end if @@ -701,7 +712,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) endif return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -713,8 +724,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -735,15 +747,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -762,6 +814,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 b/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 index 36ee1be358..5f21fbf4d9 100644 --- a/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 +++ b/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 @@ -50,14 +50,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -70,6 +75,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -121,7 +130,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) use ioFileMod, only: getfil use wrap_nf @@ -144,7 +153,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -167,7 +176,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_DUST, "meteor smoke", rmin, 2.0_f, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! NOTE: For CAM, the optional do_wetdep and do_drydep flags should be @@ -180,7 +189,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_SULFATE, "sulfate", rmin_sulfate, vmrat_sulfate, I_SPHERE, 1._f, .false., & rc, irhswell=I_WTPCT_H2SO4, do_wetdep=.true., do_drydep=.true., solfac=1.0_f, & scavcoef=0.1_f, is_sulfate=.true., shortname="SULF") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -189,15 +198,15 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, & I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_SULFATE, I_GRP_SULFATE, "sulfate", RHO_SULFATE, & I_VOLATILE, I_H2SO4, rc, shortname="SULF") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_SULCORE, I_GRP_SULFATE, "sulfate core", RHO_METEOR_SMOKE, & I_COREMASS, I_METEOR_SMOKE, rc, shortname="SFCORE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes ! @@ -208,40 +217,40 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, & I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q", & ds_threshold=0.2_f) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') call CARMAGAS_Create(carma, I_GAS_H2SO4, "Sulfuric Acid", WTMOL_H2SO4, & I_VAPRTN_H2SO4_AYERS1980, I_GCOMP_H2SO4, rc, shortname = "H2SO4", & ds_threshold=-0.2_f) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') ! Set H2SO4 to be the condensing gas, water vapor is assumed to be in equilibrium ! and will be used to define the wet particle radius. call CARMA_AddGrowth(carma, I_ELEM_SULFATE, I_GAS_H2SO4, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.') call CARMA_AddNucleation(carma, I_ELEM_SULFATE, I_ELEM_SULFATE, I_HOMNUC, 0._f, rc, igas=I_GAS_H2SO4) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') ! Also need nucleation with meteor smoke. call CARMA_AddNucleation(carma, I_ELEM_DUST, I_ELEM_SULCORE, I_HETNUCSULF, 0._f, rc, igas=I_GAS_H2SO4, ievp2elem=I_ELEM_DUST) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') call CARMA_AddCoagulation(carma, I_GRP_SULFATE, I_GRP_SULFATE, I_GRP_SULFATE, I_COLLEC_FUCHS, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') ! Dust-Sulfate Coagulation? call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_SULFATE, I_GRP_SULFATE, I_COLLEC_FUCHS, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -251,7 +260,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -276,14 +285,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -309,14 +318,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -347,10 +356,10 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -369,6 +378,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilat ! latitude index @@ -508,7 +518,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -560,7 +570,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -568,7 +578,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only: pcnst use ioFileMod, only: getfil use wrap_nf @@ -578,6 +588,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilev ! level index @@ -603,7 +614,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.") ! Initialize the emissions rate table. if (carma_do_emission) then @@ -644,7 +655,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -652,7 +663,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -721,7 +732,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! There should be one time for each day of the year, so ! quit if it isn't correct. if (carma_escale_nTimes .ne. 365) then - call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") + call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") endif call wrap_inq_dimid(fid, "ltime", ltime_did) @@ -744,7 +755,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call wrap_inq_varid(fid, 'SGRF', grf_vid) tmp = nf90_get_var (fid, grf_vid, carma_escale_grf) if (tmp/=NF90_NOERR) then - write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid + write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid call handle_error (tmp) end if @@ -780,7 +791,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) endif return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -792,8 +803,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -814,15 +826,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -841,6 +893,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/pmc/carma_model_mod.F90 b/src/physics/carma/models/pmc/carma_model_mod.F90 index eb8c6e6667..41ac20fffe 100644 --- a/src/physics/carma/models/pmc/carma_model_mod.F90 +++ b/src/physics/carma/models/pmc/carma_model_mod.F90 @@ -45,14 +45,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -65,6 +70,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -117,7 +126,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) use ioFileMod, only: getfil use wrap_nf @@ -137,7 +146,7 @@ subroutine CARMA_DefineModel(carma, rc) integer :: imag_vid character(len=256) :: efile ! refractive index file name real(kind=f) :: interp - complex(kind=f) :: refidx_ice(NWAVE) ! the refractive index at each CAM wavelength + complex(kind=f) :: refidx_ice(NWAVE,NREFIDX) ! the refractive index at each CAM wavelength integer :: LUNOPRT logical :: do_print @@ -145,7 +154,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT, wave=wave) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -203,7 +212,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -227,10 +236,10 @@ subroutine CARMA_DefineModel(carma, rc) if (wave(i) > warren_wave(j)) then if (j > 1) then interp = (wave(i) - warren_wave(j-1)) / (warren_wave(j) - warren_wave(j-1)) - refidx_ice(i) = cmplx(warren_real(j-1) + interp*(warren_real(j) - warren_real(j-1)), & - warren_imag(j-1) + interp*(warren_imag(j) - warren_imag(j-1))) + refidx_ice(i,1) = cmplx(warren_real(j-1) + interp*(warren_real(j) - warren_real(j-1)), & + warren_imag(j-1) + interp*(warren_imag(j) - warren_imag(j-1)), kind=f) else - refidx_ice(i) = cmplx(warren_real(j), warren_imag(j)) + refidx_ice(i,1) = cmplx(warren_real(j), warren_imag(j), kind=f) endif exit @@ -240,8 +249,8 @@ subroutine CARMA_DefineModel(carma, rc) end if call CARMAGROUP_Create(carma, I_GRP_CRICE, "ice crystal", rmin, 2.2_f, I_SPHERE, 1._f, .true., & - rc, do_mie=carma_do_pheat, refidx=refidx_ice, shortname="CRICE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + rc, do_mie=carma_do_pheat, shortname="CRICE") + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') ! Define the Elements @@ -250,15 +259,15 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, & I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRICE, I_GRP_CRICE, "ice crystal", RHO_I, & - I_VOLATILE, I_ICE, rc, shortname="CRICE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + I_VOLATILE, I_ICE, rc, shortname="CRICE", refidx=refidx_ice) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRCORE, I_GRP_CRICE, "ice core", RHO_METEOR_SMOKE, & I_COREMASS, I_METEOR_SMOKE, rc, shortname="CRCORE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -267,25 +276,25 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Gases call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, & I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q", ds_threshold=0.2_f) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') call CARMA_AddNucleation(carma, I_ELEM_DUST, I_ELEM_CRCORE, I_HETNUC, 0._f, rc, & igas=I_GAS_H2O, ievp2elem=I_ELEM_DUST) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') call CARMA_AddGrowth(carma, I_ELEM_CRICE, I_GAS_H2O, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.') call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_CRICE, I_GRP_CRICE, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -295,7 +304,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -320,14 +329,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -353,14 +362,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -391,10 +400,10 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -413,6 +422,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilat ! latitude index @@ -552,7 +562,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -598,7 +608,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -606,7 +616,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use ioFileMod, only: getfil use constituents, only: pcnst use wrap_nf @@ -616,6 +626,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilev ! level index @@ -641,7 +652,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.") ! Initialize the emissions rate table. if (carma_do_emission) then @@ -682,7 +693,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -690,7 +701,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -759,7 +770,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! There should be one time for each day of the year, so ! quit if it isn't correct. if (carma_escale_nTimes .ne. 365) then - call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") + call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") endif call wrap_inq_dimid(fid, "ltime", ltime_did) @@ -782,7 +793,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call wrap_inq_varid(fid, 'SGRF', grf_vid) tmp = nf90_get_var (fid, grf_vid, carma_escale_grf) if (tmp/=NF90_NOERR) then - write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid + write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid call handle_error (tmp) end if @@ -818,7 +829,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) endif return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -830,8 +841,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -852,15 +864,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -879,6 +931,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 b/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 index 4a9e08d5be..166bb66f3d 100644 --- a/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 +++ b/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 @@ -223,7 +223,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -617,7 +617,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -753,7 +753,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -761,7 +761,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -953,4 +953,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/src/physics/carma/models/sea_salt/carma_model_mod.F90 b/src/physics/carma/models/sea_salt/carma_model_mod.F90 index db01fb4b00..0f1aa889dd 100644 --- a/src/physics/carma/models/sea_salt/carma_model_mod.F90 +++ b/src/physics/carma/models/sea_salt/carma_model_mod.F90 @@ -44,14 +44,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -64,6 +69,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -83,7 +92,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -100,7 +109,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Report model specific configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -117,7 +126,7 @@ subroutine CARMA_DefineModel(carma, rc) rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALT", irhswell=I_GERBER, & irhswcomp=I_SWG_SEA_SALT) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -125,7 +134,7 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "sea salt", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -137,7 +146,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -147,7 +156,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -172,14 +181,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -205,14 +214,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -243,7 +252,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -252,7 +261,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Tianyi Fan, Chuck Bardeen !! @version Dec-2010 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -270,6 +279,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: lchnk ! chunk identifier @@ -439,7 +449,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend !********************************** ! wet sea salt radius at RH = 80% !********************************** - r80cm = (c1 * (r(ibin)) ** c2 / (c3 * r(ibin) ** c4 - log10(0.8)) + (r(ibin))**3) ** (1./3.) ! [cm] + r80cm = (c1 * (r(ibin)) ** c2 / (c3 * r(ibin) ** c4 - log10(0.8_r8)) + (r(ibin))**3) ** (1._r8/3._r8) ! [cm] rdrycm = r(ibin) ! [cm] r80 = r80cm *1.e4_r8 ! [um] rdry = rdrycm*1.e4_r8 ! [um] @@ -452,7 +462,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend !********************************** ! WIND for seasalt production !********************************** - call CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc) + call CARMAMODEL_SurfaceWind(carma, state, icol, cam_in, u10in, rc) ! Add any surface flux here. ncflx = 0.0_r8 @@ -542,7 +552,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend !Monahan B_mona = (0.38_r8 - log10(r80)) / 0.65_r8 Monahan = 1.373_r8 * (u10in**3.41_r8) * r80**(-3._r8) * & - (1._r8 + 0.057 *r80**1.05_r8) * 10._r8 ** (1.19_r8 * exp(-1. * B_mona**2)) ! dF/dr + (1._r8 + 0.057_r8 *r80**1.05_r8) * 10._r8 ** (1.19_r8 * exp(-1._r8 * B_mona**2)) ! dF/dr !Smith u14 = u10in * (1._r8 + cd_smith**0.5_r8 / xkar * log(14._r8 / 10._r8)) ! 14 meter wind @@ -641,7 +651,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -649,13 +659,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only: pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -664,7 +675,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -676,8 +687,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -698,15 +710,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -725,14 +777,14 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition !! Calculate the sea surface wind with a Weibull distribution. !! !! @author Tianyi Fan !! @version August-2010 - subroutine CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc) + subroutine CARMAMODEL_SurfaceWind(carma, state, icol, cam_in, u10in, rc) use ppgrid, only: pcols, pver use physics_types, only: physics_state use camsrfexch, only: cam_in_t @@ -765,7 +817,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc) u10in = uWB341 ** (1._r8 / 3.41_r8) return - end subroutine CARMA_SurfaceWind + end subroutine CARMAMODEL_SurfaceWind !! Calculate the nth mean of u using Weibull wind distribution @@ -794,7 +846,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) if (present(wbk)) then k = wbk else - k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR + k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR ! k = 2.5_r8 ! Lansing's estimate end if @@ -809,4 +861,119 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) end subroutine WeibullWind -end module + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics + +end module carma_model_mod diff --git a/src/physics/carma/models/sulfate/carma_model_mod.F90 b/src/physics/carma/models/sulfate/carma_model_mod.F90 index abf98d1820..c19e013891 100644 --- a/src/physics/carma/models/sulfate/carma_model_mod.F90 +++ b/src/physics/carma/models/sulfate/carma_model_mod.F90 @@ -38,15 +38,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition - + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -59,6 +63,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -90,7 +98,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) use physics_buffer, only: pbuf_add_field, dtype_r8 type(carma_type), intent(inout) :: carma !! the carma object @@ -172,7 +180,7 @@ subroutine CARMA_DefineModel(carma, rc) call pbuf_add_field('VOLC_MMR', 'global', dtype_r8, (/pcols, pver/), ipbuf4so4mmr) endif - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -182,7 +190,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -207,14 +215,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -240,14 +248,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t use physics_buffer, only: pbuf_get_field @@ -325,7 +333,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end if - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -334,7 +342,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Tianyi Fan, Chuck Bardeen !! @version Dec-2010 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -353,6 +361,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -365,7 +374,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency = 0._r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -373,20 +382,21 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. rc = RC_OK return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -398,7 +408,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -420,7 +430,49 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add @@ -428,7 +480,7 @@ end subroutine CARMA_InitializeParticle !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -447,6 +499,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_detrain/carma_model_mod.F90 b/src/physics/carma/models/test_detrain/carma_model_mod.F90 index 16e6cb431f..fde34f8b20 100644 --- a/src/physics/carma/models/test_detrain/carma_model_mod.F90 +++ b/src/physics/carma/models/test_detrain/carma_model_mod.F90 @@ -472,4 +472,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_growth/carma_model_mod.F90 b/src/physics/carma/models/test_growth/carma_model_mod.F90 index ad57aed469..5b4a2b6ac7 100644 --- a/src/physics/carma/models/test_growth/carma_model_mod.F90 +++ b/src/physics/carma/models/test_growth/carma_model_mod.F90 @@ -10,10 +10,10 @@ !! the initial conditions of the particles. Each realization of CARMA !! microphysics has its own version of this file. !! -!! This file is a simple test case involving one group of dust particles and -!! 8 size bins. Optical properties are calculated, assuming a constant refractive -!! index of (1.55, 4e-3). The particles are not subject to particle swelling, but -!! do coagulate. +!! This file is a simple test case involving two groups: sulfate condensation nuclei +!! and ice particles. The sulfates are prescribed and the ice is prognostics. This +!! test exercises the nucleation and growth code. THe particles are sedimented, but +!! do not coagulate. !! !! @version May-2009 !! @author Chuck Bardeen @@ -43,14 +43,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -63,6 +68,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -93,7 +102,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -118,11 +127,11 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_CRCN, "Sulfate CN", rmin_cn, 4.0_f, I_SPHERE, 1._f, .false., & rc, shortname="CRCN", cnsttype=I_CNSTTYPE_DIAGNOSTIC, & do_vtran=.false.) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, I_GRP_CRICE, "Ice", rmin_ice, 2.8_f, I_HEXAGON, 1._f / 6._f, .true., & rc, shortname="CRICE", ifallrtn=I_FALLRTN_STD_SHAPE) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') @@ -132,30 +141,30 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_CRCN, I_GRP_CRCN, "Sulfate CN", RHO_CN, & I_INVOLATILE, I_H2SO4, rc, shortname="CRCN", isolute=I_SOL_CRH2SO4) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRICE, I_GRP_CRICE, "Ice", RHO_I, & I_VOLATILE, I_ICE, rc, shortname="CRICE") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRCORE, I_GRP_CRICE, "Core Mass", RHO_CN, & I_COREMASS, I_H2SO4, rc, shortname="CRCORE", isolute=1) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') ! Define the Solutes call CARMASOLUTE_Create(carma, I_SOL_CRH2SO4, "Sulfuric Acid", 2, 98._f, 1.38_f, rc, shortname="CRH2SO4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMASOLUTE_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMASOLUTE_Create failed.') ! Define the Gases call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') ! Define the Processes call CARMA_AddGrowth(carma, I_ELEM_CRICE, I_GAS_H2O, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.') ! NOTE: For now, assume the latent heat for nucleation is the latent of of fusion of ! water, using the CAM constant (scaled from J/kg to erg/g). @@ -165,10 +174,10 @@ subroutine CARMA_DefineModel(carma, rc) ! the gas associated with nucleation is accounted for. call CARMA_AddNucleation(carma, I_ELEM_CRCN, I_ELEM_CRCORE, & I_AERFREEZE + I_AF_KOOP_2000, 0._f, rc, igas=I_GAS_H2O, ievp2elem=I_ELEM_CRCN) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -178,7 +187,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -203,14 +212,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -249,7 +258,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! Get the air density. call CARMASTATE_GetState(cstate, rc, rhoa_wet=rhoa_wet) - if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMASTATE_GetState failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMASTATE_GetState failed.') ! Use a fixed sulfate size distribution. By doing this as a diagnostic group, ! the constituents for the sulfate bins do not need to be advected, which @@ -258,7 +267,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ielem = 1 call CARMAGROUP_Get(carma, igroup, rc, r=r, dr=dr, rmass=rmass) - if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMAGROUP_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMAGROUP_Get failed.') arg1(:) = n * dr(:) / (sqrt(2._f*PI) * r(:) * log(rsig)) arg2(:) = -((log(r(:)) - log(r0))**2) / (2._f*(log(rsig))**2) @@ -268,18 +277,18 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr do ibin = 1, NBIN mmr(ibin, :) = rhop(ibin) / rhoa_wet(:) call CARMASTATE_SetBin(cstate, ielem, ibin, mmr(ibin, :), rc) - if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMAGROUP_SetBin failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMAGROUP_SetBin failed.') end do return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -310,7 +319,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -319,7 +328,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -338,6 +347,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -370,7 +380,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -381,13 +391,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -396,7 +407,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -408,7 +419,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -431,31 +442,65 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! Put a horizontally uniform layer of the smallest bin size ! in the model. if (ibin == 1) then - if (ielem == I_ELEM_CRICE) then - where(mask) - q(:, plev/4) = 100e-7_r8 ! 1/4 - end where - end if - if (ielem == I_ELEM_CRCORE) then - where(mask) - q(:, plev/4) = 100e-9_r8 ! 1/4 - end where - end if + where(mask) +! q(:, 1) = 100e-9_r8 ! top + q(:, plev/4) = 100e-9_r8 ! 1/4 ! q(:, plev/2) = 100e-9_r8 ! middle ! q(:, 3*plev/4) = 100e-9_r8 ! 3/4 ! q(:, plev-1) = 100e-9_r8 ! bottom + end where end if return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -474,6 +519,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_passive/carma_model_mod.F90 b/src/physics/carma/models/test_passive/carma_model_mod.F90 index 12f4a6168e..150f1d8a5f 100644 --- a/src/physics/carma/models/test_passive/carma_model_mod.F90 +++ b/src/physics/carma/models/test_passive/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -62,6 +67,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -79,7 +88,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -101,7 +110,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, 1, "Dust", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.15_f, & scavcoef=0.1_f, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -109,7 +118,7 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -120,10 +129,10 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, 1, 1, 1, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -133,7 +142,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -158,14 +167,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -191,14 +200,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -229,7 +238,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -238,7 +247,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -257,6 +266,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -289,7 +299,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -300,13 +310,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -315,7 +326,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -327,7 +338,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -360,15 +371,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end if return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -387,6 +438,95 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_radiative/carma_model_mod.F90 b/src/physics/carma/models/test_radiative/carma_model_mod.F90 index 8acff28edb..d1b248df5a 100644 --- a/src/physics/carma/models/test_radiative/carma_model_mod.F90 +++ b/src/physics/carma/models/test_radiative/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -65,6 +70,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) = (/ 0._f, 0.5_f, 0.7_f, 0.8_f, 0.9_f, 0.95_f, 0.98_f, 0.99_f /) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -82,7 +91,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -90,14 +99,14 @@ subroutine CARMA_DefineModel(carma, rc) real(kind=f), parameter :: RHO_DUST = 2.0_f ! density of dust particles (g/cm) real(kind=f), parameter :: rmin = 1e-5_f ! minimum radius (cm) real(kind=f), parameter :: vmrat = 2.0_f ! volume ratio - complex(kind=f) :: refidx(NWAVE) ! refractice indices + complex(kind=f) :: refidx(NWAVE, NREFIDX) ! refractice indices ! Default return code. rc = RC_OK ! Use the same refractive index at all wavelengths. This value is typical of dust in ! the visible. - refidx(:) = (1.55_f, 4e-3_f) + refidx(:,1) = (1.55_f, 4e-3_f) ! Define the Groups ! @@ -108,16 +117,16 @@ subroutine CARMA_DefineModel(carma, rc) ! should also be defined. call CARMAGROUP_Create(carma, 1, "Dust", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.15_f, & - scavcoef=0.1_f, shortname="DUST", refidx=refidx, do_mie=.true.) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + scavcoef=0.1_f, shortname="DUST", do_mie=.true.) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements ! ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. - call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST", refidx=refidx) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -128,10 +137,10 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, 1, 1, 1, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -141,7 +150,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -166,14 +175,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -199,14 +208,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -237,7 +246,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -246,7 +255,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -265,6 +274,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -297,7 +307,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -308,13 +318,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -323,7 +334,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -335,7 +346,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -368,15 +379,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end if return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -395,6 +446,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_swelling/carma_model_mod.F90 b/src/physics/carma/models/test_swelling/carma_model_mod.F90 index ce55401475..4e98bb5cd1 100644 --- a/src/physics/carma/models/test_swelling/carma_model_mod.F90 +++ b/src/physics/carma/models/test_swelling/carma_model_mod.F90 @@ -43,14 +43,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 3 !! Number of particle groups @@ -63,6 +68,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -80,7 +89,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -100,19 +109,19 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, 1, "None", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') call CARMAGROUP_Create(carma, 2, "Fitzgerald", rmin, vmrat, I_SPHERE, 1._f, & .false., rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALTFZ", irhswell=I_FITZGERALD, & irhswcomp=I_SWF_NACL) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') call CARMAGROUP_Create(carma, 3, "Gerber", rmin, vmrat, I_SPHERE, 1._f, & .false., rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALTGB", irhswell=I_GERBER, & irhswcomp=I_SWG_SEA_SALT) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -120,13 +129,13 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "None", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, 2, 2, "Fitz", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALTFZ") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, 3, 3, "Gerb", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALTGB") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -138,7 +147,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -148,7 +157,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -173,14 +182,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -206,14 +215,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -244,7 +253,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -253,7 +262,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -272,6 +281,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -304,7 +314,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -312,13 +322,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -327,7 +338,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -339,7 +350,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -369,15 +380,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end where return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -396,6 +447,95 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_tracers/carma_model_mod.F90 b/src/physics/carma/models/test_tracers/carma_model_mod.F90 index 9ed84a9471..40aa2b911c 100644 --- a/src/physics/carma/models/test_tracers/carma_model_mod.F90 +++ b/src/physics/carma/models/test_tracers/carma_model_mod.F90 @@ -49,14 +49,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 6 !! Number of particle groups @@ -69,6 +74,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -98,7 +107,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -112,7 +121,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -132,22 +141,22 @@ subroutine CARMA_DefineModel(carma, rc) ! defined. If wetdep is defined, then the optional solubility factor ! should also be defined. call CARMAGROUP_Create(carma, 1, "Region 1", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 2, "Region 2", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 3, "Region 3", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 4, "Region 4", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 5, "Region 5", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 6, "Rest of World", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') ! Define the Elements @@ -155,22 +164,22 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "Region 1", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 2, 2, "Region 2", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 3, 3, "Region 3", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 4, 4, "Region 4", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 5, 5, "Region 5", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 6, 6, "Rest of World", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') ! Define the Solutes @@ -183,7 +192,7 @@ subroutine CARMA_DefineModel(carma, rc) return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -193,7 +202,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair, cappa @@ -219,14 +228,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -252,7 +261,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. @@ -262,7 +271,7 @@ end subroutine CARMA_DiagnoseBins !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver @@ -325,7 +334,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end if return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. @@ -352,7 +361,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -372,6 +381,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure real(r8) :: lat(state%ncol) ! latitude (degrees) @@ -489,7 +499,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -500,20 +510,22 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst + implicit none type(carma_type), intent(inout) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. rc = RC_OK return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -525,7 +537,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -552,15 +564,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end do return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -579,6 +631,93 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_tracers2/carma_model_mod.F90 b/src/physics/carma/models/test_tracers2/carma_model_mod.F90 index ecb3324ed8..d6a74c4d12 100644 --- a/src/physics/carma/models/test_tracers2/carma_model_mod.F90 +++ b/src/physics/carma/models/test_tracers2/carma_model_mod.F90 @@ -49,14 +49,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 7 !! Number of particle groups @@ -69,6 +74,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -99,7 +108,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -113,7 +122,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -133,25 +142,25 @@ subroutine CARMA_DefineModel(carma, rc) ! defined. If wetdep is defined, then the optional solubility factor ! should also be defined. call CARMAGROUP_Create(carma, 1, "Region 1", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 2, "Region 2", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 3, "Region 3", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 4, "Region 4", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 5, "Region 5", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 6, "Region 6", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 7, "Rest of World", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG7") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') ! Define the Elements @@ -159,25 +168,25 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "Region 1", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 2, 2, "Region 2", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 3, 3, "Region 3", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 4, 4, "Region 4", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 5, 5, "Region 5", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 6, 6, "Region 6", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 7, 7, "Rest of World", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG7") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') ! Define the Solutes @@ -190,7 +199,7 @@ subroutine CARMA_DefineModel(carma, rc) return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -200,7 +209,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair, cappa @@ -226,14 +235,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -259,7 +268,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. @@ -269,7 +278,7 @@ end subroutine CARMA_DiagnoseBins !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver @@ -332,7 +341,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end if return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. @@ -359,7 +368,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -379,6 +388,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure real(r8) :: lat(state%ncol) ! latitude (degrees) @@ -497,7 +507,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -508,20 +518,21 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(inout) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. rc = RC_OK return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -533,7 +544,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -560,15 +571,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end do return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -587,6 +638,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/tholin/carma_model_mod.F90 b/src/physics/carma/models/tholin/carma_model_mod.F90 index 460971db9d..ac5216f130 100755 --- a/src/physics/carma/models/tholin/carma_model_mod.F90 +++ b/src/physics/carma/models/tholin/carma_model_mod.F90 @@ -102,7 +102,7 @@ subroutine CARMA_DefineModel(carma, rc) integer, intent(out) :: rc !! return code, negative indicates failure ! Local variables - real(kind=f) :: RHO_THOLIN = 0.64 ! density of tholin particles (g/cm) + real(kind=f) :: RHO_THOLIN = 0.64_f ! density of tholin particles (g/cm) real(kind=f), parameter :: tholin_rmin = 1.e-7_f ! dust minimum radius (cm) real(kind=f), parameter :: tholin_vmrat = 2.5_f ! dust volume ratio @@ -509,7 +509,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -517,7 +517,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -639,4 +639,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/test/system/TR8.sh b/test/system/TR8.sh index cbdb400463..22ec597f5d 100755 --- a/test/system/TR8.sh +++ b/test/system/TR8.sh @@ -10,6 +10,8 @@ ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/cam rc=$? ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/camrt rc=`expr $? + $rc` +ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/carma +rc=`expr $? + $rc` ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/rrtmg -s aer_src rc=`expr $? + $rc` ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/rrtmgp -s data,ext @@ -27,6 +29,8 @@ ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/cam rc=$? ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/camrt rc=`expr $? + $rc` +ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/carma +rc=$? ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/rrtmg -s aer_src rc=`expr $? + $rc` ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/rrtmgp -s data,ext From ee4a28bd6562e773e8d69dddc79eefce3575ee40 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 4 Dec 2024 11:14:37 -0700 Subject: [PATCH 47/89] correct the AOASRC name modified: src/physics/cam/aoa_tracers.F90 --- src/physics/cam/aoa_tracers.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/physics/cam/aoa_tracers.F90 b/src/physics/cam/aoa_tracers.F90 index fc656ad618..2d42853756 100644 --- a/src/physics/cam/aoa_tracers.F90 +++ b/src/physics/cam/aoa_tracers.F90 @@ -34,10 +34,10 @@ module aoa_tracers character(len=4), parameter :: c_names(ncnst) = (/'AOA1', 'HORZ', 'VERT'/) ! constituent source/sink names - character(len=8), parameter :: src_names(ncnst) = (/'AOAMFSRC', 'HORZSRC ', 'VERTSRC '/) + character(len=7), parameter :: src_names(ncnst) = (/'AOA1SRC', 'HORZSRC', 'VERTSRC'/) integer :: ifirst = -1 ! global index of first constituent - integer :: ixaoa = -1 ! global index for AOAMFSRC tracer + integer :: ixaoa = -1 ! global index for AOA1SRC tracer integer :: ixht = -1 ! global index for HORZ tracer integer :: ixvt = -1 ! global index for VERT tracer @@ -347,7 +347,7 @@ subroutine aoa_tracers_timestep_tend(state, ptend, dt) lchnk = state%lchnk ncol = state%ncol - ! AOAMF + ! AOA1 xmmr = mmr0*(1._r8 + per_yr*years) ptend%q(1:ncol,pver,ixaoa) = (xmmr - state%q(1:ncol,pver,ixaoa)) / dt @@ -403,7 +403,7 @@ subroutine init_cnst_3d(m, latvals, lonvals, mask, q) if (m == ixaoa) then - ! AOAMF + ! AOA1 q(:,:) = 0.0_r8 else if (m == ixht) then From 398d956452e78ea36e1101cf18b9a5069ce21ca0 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 4 Dec 2024 16:16:47 -0700 Subject: [PATCH 48/89] set carma_sulfnuc_method namelist option modified: bld/build-namelist modified: bld/namelist_files/namelist_definition.xml --- bld/build-namelist | 3 ++- bld/namelist_files/namelist_definition.xml | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/bld/build-namelist b/bld/build-namelist index 66c3574a62..29c7d6b316 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -1268,6 +1268,7 @@ if ($carma ne 'none') { add_default($nl, 'carma_model', 'val'=>$carma); add_default($nl, 'carma_flag', 'val'=>'.true.'); add_default($nl, 'history_carma', 'val'=>'.true.'); + add_default($nl, 'carma_sulfnuc_method','val'=>'ZhaoTurco'); } if ($carma eq 'bc_strat') { add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); @@ -1587,7 +1588,7 @@ if (defined $nl->get_value('prescribed_strataero_3modes')) { # determine if prescribed stratospheric aerosol data is needed if ( ($het_chem) || ($nl->get_value('prescribed_strataero_feedback') =~ /$TRUE/io ) ){ - if ( ($carma ne 'sulfate') && !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols + if ( !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols unless (defined $nl->get_value('prescribed_strataero_type')) { add_default($nl, 'prescribed_strataero_type','val'=>'CYCLICAL'); diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index bd003c779a..d216f837f1 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -4476,6 +4476,20 @@ is not active. Default: none + + Nucleation methods: + ZhaoTurco + Zhao and Turco, JAS, V.26, No.5, 1995. + Vehkamaki + Vehkamaki, H., M. Kulmala, I. Napari, K.E.J. Lehtinen, + C. Timmreck, M. Noppel and A. Laaksonen, 2002, + An improved parameterization for sulfuric acid-water nucleation + rates for tropospheric and stratospheric conditions, + J. Geophys. Res., 107, 4622, doi:10.1029/2002jd002184 +Default: none + + A fraction that scales how tight the convergence criteria are to From ea7b2484f69a9c3aece4ba318c15e04c550854f4 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 5 Dec 2024 08:51:33 -0700 Subject: [PATCH 49/89] change derecho 10x15 res tests to 4x5 modified: cime_config/testdefs/testlist_cam.xml modified: cime_config/config_pes.xml --- cime_config/config_pes.xml | 16 ++-- cime_config/testdefs/testlist_cam.xml | 110 +++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 11 deletions(-) diff --git a/cime_config/config_pes.xml b/cime_config/config_pes.xml index 47bbcc4af3..f488c21b27 100644 --- a/cime_config/config_pes.xml +++ b/cime_config/config_pes.xml @@ -1678,14 +1678,14 @@ none - 32 - 32 - 32 - 32 - 32 - 32 - 32 - 32 + 36 + 36 + 36 + 36 + 36 + 36 + 36 + 36 1 diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index 2801e231f7..d4fc9d40a8 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -583,6 +583,14 @@ + + + + + + + + @@ -605,6 +613,14 @@ + + + + + + + + @@ -616,7 +632,15 @@ - + + + + + + + + + @@ -628,6 +652,14 @@ + + + + + + + + @@ -640,6 +672,14 @@ + + + + + + + + @@ -651,6 +691,14 @@ + + + + + + + + @@ -659,9 +707,17 @@ - + + + + + + + + + @@ -673,6 +729,14 @@ + + + + + + + + @@ -684,6 +748,14 @@ + + + + + + + + @@ -696,6 +768,14 @@ + + + + + + + + @@ -743,6 +823,14 @@ + + + + + + + + @@ -754,6 +842,14 @@ + + + + + + + + @@ -762,9 +858,17 @@ - + + + + + + + + + From 9d32d137223c07fc873aad2e5277a767d21687eb Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 6 Dec 2024 13:21:36 -0500 Subject: [PATCH 50/89] add UT and UQ to cam_diagnostics.F90 --- doc/ChangeLog | 17 +++++++++++++++++ src/physics/cam/cam_diagnostics.F90 | 14 +++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9e152b8e88..ea4766c48d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -25,6 +25,11 @@ Issue #670 - DAE test broken - ChangeLog indicates that this test has never worked since it was added in cam6_2_046 (2020-09-01). Test removed. +Issue #807 - add UT and UQ to cam_diagnostics + - Add UT and UQ. Note that other possible fields mentioned in the issue, + i.e., OMEGA2, OMEGAQ, OMEGAU, and OMEGAV, are already implemented. + OMEGA2 is called OMGAOMGA. + Describe any changes made to build system: none Describe any changes made to the namelist: none @@ -96,6 +101,18 @@ src/chemistry/mozart/mo_drydep.F90 . get_landuse_and_soilw_from_file - restrict the INFO messages to only print from masterproc +src/physics/cam/cam_diagnostics.F90 +. diag_init_dry + - add addfld call for UT, and corresponding add_default for UT inside the + history_eddy conditional. +. diag_phys_writeout_dry + - add calculation and outfld call for UT +. diag_init_moist + - add addfld call for UQ, and corresponding add_default for UQ inside the + history_eddy conditional. +. diag_phys_writeout_moist + - add calculation and outfld call for UQ + src/physics/cam/microp_aero.F90 . microp_aero_run - add condition that number of bulk aerosols must be > 0 before calling diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 97dad2ba01..3769d42953 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -253,6 +253,7 @@ subroutine diag_init_dry(pbuf2d) call addfld ('OMEGAV', (/ 'lev' /), 'A', 'm Pa/s2 ', 'Vertical flux of meridional momentum' ) call addfld ('OMGAOMGA', (/ 'lev' /), 'A', 'Pa2/s2', 'Vertical flux of vertical momentum' ) + call addfld ('UT', (/ 'lev' /), 'A', 'K m/s ', 'Zonal heat transport') call addfld ('UU', (/ 'lev' /), 'A', 'm2/s2', 'Zonal velocity squared' ) call addfld ('WSPEED', (/ 'lev' /), 'X', 'm/s', 'Horizontal total wind speed maximum' ) call addfld ('WSPDSRFMX', horiz_only, 'X', 'm/s', 'Horizontal total wind speed maximum at surface layer midpoint' ) @@ -339,6 +340,7 @@ subroutine diag_init_dry(pbuf2d) call add_default ('VT ', 1, ' ') call add_default ('VU ', 1, ' ') call add_default ('VV ', 1, ' ') + call add_default ('UT ', 1, ' ') call add_default ('UU ', 1, ' ') call add_default ('OMEGAT ', 1, ' ') call add_default ('OMEGAU ', 1, ' ') @@ -438,6 +440,7 @@ subroutine diag_init_moist(pbuf2d) ! outfld calls in diag_phys_writeout call addfld ('OMEGAQ', (/ 'lev' /), 'A', 'kgPa/kgs', 'Vertical water transport' ) + call addfld ('UQ', (/ 'lev' /), 'A', 'm/skg/kg', 'Zonal water transport') call addfld ('VQ', (/ 'lev' /), 'A', 'm/skg/kg', 'Meridional water transport') call addfld ('QQ', (/ 'lev' /), 'A', 'kg2/kg2', 'Eddy moisture variance') @@ -611,6 +614,7 @@ subroutine diag_init_moist(pbuf2d) end if if (history_eddy) then + call add_default ('UQ ', 1, ' ') call add_default ('VQ ', 1, ' ') endif @@ -1017,6 +1021,9 @@ subroutine diag_phys_writeout_dry(state, pbuf, p_surf_t) ! ! zonal advection ! + ftem(:ncol,:) = state%u(:ncol,:)*state%t(:ncol,:) + call outfld ('UT ',ftem ,pcols ,lchnk ) + ftem(:ncol,:) = state%u(:ncol,:)**2 call outfld ('UU ',ftem ,pcols ,lchnk ) @@ -1281,9 +1288,10 @@ subroutine diag_phys_writeout_moist(state, pbuf, p_surf_t) call outfld('PDELDRY', state%pdeldry, pcols, lchnk) call outfld('PDEL', state%pdel, pcols, lchnk) - ! - ! Meridional advection fields - ! + + ftem(:ncol,:) = state%u(:ncol,:)*state%q(:ncol,:,ixq) + call outfld ('UQ ',ftem ,pcols ,lchnk ) + ftem(:ncol,:) = state%v(:ncol,:)*state%q(:ncol,:,ixq) call outfld ('VQ ',ftem ,pcols ,lchnk ) From 45860703ae083b6e655507e2acc645577d133a19 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 6 Dec 2024 14:07:06 -0500 Subject: [PATCH 51/89] fix for history_eddy option --- doc/ChangeLog | 5 +++++ src/physics/cam/vertical_diffusion.F90 | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index ea4766c48d..0766808971 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -123,6 +123,11 @@ src/physics/cam/nucleate_ice_cam.F90 - add conditionals so naer2 array not referenced when there are no aerosols. +src/physics/cam/vertical_diffusion.F90 +. vertical_diffusion_init + - fix conditional around add_default call for UFLX and VFLX so those + fields aren't added if they're not computed. + src/physics/cam7/physpkg.F90 . tphysbc - add conditionals so modal aerosol calculations only called when modal diff --git a/src/physics/cam/vertical_diffusion.F90 b/src/physics/cam/vertical_diffusion.F90 index 472b2a5501..e2d571a4de 100644 --- a/src/physics/cam/vertical_diffusion.F90 +++ b/src/physics/cam/vertical_diffusion.F90 @@ -619,8 +619,10 @@ subroutine vertical_diffusion_init(pbuf2d) endif if (history_eddy) then - call add_default( 'UFLX ', 1, ' ' ) - call add_default( 'VFLX ', 1, ' ' ) + if (.not. do_pbl_diags) then + call add_default( 'UFLX ', 1, ' ' ) + call add_default( 'VFLX ', 1, ' ' ) + end if endif if( history_budget ) then From fa69b875ca03e801463b7f23a2c04bd5f9722aa2 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 11 Dec 2024 13:56:30 -0700 Subject: [PATCH 52/89] more sane way to control nitrogen deposition to surface models modified: bld/build-namelist modified: bld/namelist_files/namelist_defaults_cam.xml modified: bld/namelist_files/namelist_definition.xml modified: bld/namelist_files/use_cases/1850_cam_lt.xml modified: bld/namelist_files/use_cases/1850_cam_mt.xml modified: bld/namelist_files/use_cases/hist_cam_lt.xml modified: bld/namelist_files/use_cases/hist_cam_mt.xml modified: cime_config/buildnml modified: cime_config/config_component.xml modified: src/chemistry/mozart/chemistry.F90 modified: src/chemistry/mozart/mo_chm_diags.F90 modified: src/chemistry/pp_none/chemistry.F90 modified: src/control/camsrfexch.F90 modified: src/control/runtime_opts.F90 modified: src/cpl/nuopc/atm_import_export.F90 modified: src/cpl/nuopc/atm_stream_ndep.F90 modified: src/physics/cam/cam_diagnostics.F90 modified: src/utils/srf_field_check.F90 --- bld/build-namelist | 8 --- bld/namelist_files/namelist_defaults_cam.xml | 7 ++ bld/namelist_files/namelist_definition.xml | 19 ++--- bld/namelist_files/use_cases/1850_cam_lt.xml | 7 ++ bld/namelist_files/use_cases/1850_cam_mt.xml | 7 ++ bld/namelist_files/use_cases/hist_cam_lt.xml | 7 ++ bld/namelist_files/use_cases/hist_cam_mt.xml | 7 ++ cime_config/buildnml | 12 ---- cime_config/config_component.xml | 73 ------------------- src/chemistry/mozart/chemistry.F90 | 15 ++-- src/chemistry/mozart/mo_chm_diags.F90 | 5 ++ src/chemistry/pp_none/chemistry.F90 | 35 ++++----- src/control/camsrfexch.F90 | 30 ++++---- src/control/runtime_opts.F90 | 2 + src/cpl/nuopc/atm_import_export.F90 | 76 ++++++++------------ src/cpl/nuopc/atm_stream_ndep.F90 | 67 +++++++++-------- src/physics/cam/cam_diagnostics.F90 | 10 +++ src/utils/srf_field_check.F90 | 12 ---- 18 files changed, 170 insertions(+), 229 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index 66c3574a62..6dd96595d9 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -509,14 +509,6 @@ if ($phys_mode_flags > 1) { my $simple_phys = 0; if ($adia_mode or $ideal_mode) { $simple_phys = 1; } -# If running either a simple physics or an aquaplanet configuration, the nitrogen -# deposition data is not used. These files are set in buildnml and can't be overridden -# via user_nl_cam. So provide an override here. -if ($simple_phys or $aqua_mode) { - $nl->set_variable_value('ndep_stream_nl', 'stream_ndep_data_filename', '" "'); - $nl->set_variable_value('ndep_stream_nl', 'stream_ndep_mesh_filename', '" "'); -} - # Single column mode my $scam = $cfg->get('scam'); my $scam_iop = $cfg->get('scam_iop'); diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 462570da4a..ab2707290c 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2060,6 +2060,13 @@ atm/cam/dst/dst_source2x2tuned-cam4-06132012.nc atm/cam/dst/dst_source1x1tuned-cam4-06202012.nc + +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +2000 +2000 +1 + .false. .true. diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index bd003c779a..4aaa038224 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -7609,40 +7609,29 @@ Bubble-mediated sea-air transfer. See ocean_emis.F90 for details. Default: FALSE - -List of nitrogen deposition fluxes to be sent from CAM to surface models. -Default: set by build-namelist. - - -Year first to use in nitrogen deposition stream data. Set by case xml variable -CAM_STREAM_NDEP_YEAR_FIRST +Year first to use in nitrogen deposition stream data. Year last to use in nitrogen deposition stream data. -Set by case xml variable CAM_STREAM_NDEP_YEAR_LAST -Model year to align with CAM_STREAM_NDEP_YEAR_FIRST. -Set by case xml variable CAM_STREAM_NDEP_YEAR_ALIGN +Model year to align with stream_ndep_year_first. -NDEP stream data filename. -Set by case xml variable CAM_STREAM_NDEP_DATA_FILENAME. +Nitrogen deposition stream data filename. -NDEP mesh file corresponding to sream_ndep_data_filename. -Set by case xml variable CAM_STREAM_NDEP_MESH_FILENAME. +Grid mesh file corresponding to stream_ndep_data_filename. CYCLICAL 1850 + +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +1850 +1850 +1 + diff --git a/bld/namelist_files/use_cases/1850_cam_mt.xml b/bld/namelist_files/use_cases/1850_cam_mt.xml index 5a535f27be..df05241070 100644 --- a/bld/namelist_files/use_cases/1850_cam_mt.xml +++ b/bld/namelist_files/use_cases/1850_cam_mt.xml @@ -56,4 +56,11 @@ CYCLICAL 1850 + +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +1850 +1850 +1 + diff --git a/bld/namelist_files/use_cases/hist_cam_lt.xml b/bld/namelist_files/use_cases/hist_cam_lt.xml index c436b97c1f..a7cd6c0e9c 100644 --- a/bld/namelist_files/use_cases/hist_cam_lt.xml +++ b/bld/namelist_files/use_cases/hist_cam_lt.xml @@ -42,4 +42,11 @@ INTERP_MISSING_MONTHS SERIAL + +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +1850 +2015 +1850 + diff --git a/bld/namelist_files/use_cases/hist_cam_mt.xml b/bld/namelist_files/use_cases/hist_cam_mt.xml index c100cc6e85..63b6691929 100644 --- a/bld/namelist_files/use_cases/hist_cam_mt.xml +++ b/bld/namelist_files/use_cases/hist_cam_mt.xml @@ -37,4 +37,11 @@ INTERP_MISSING_MONTHS SERIAL + +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +1850 +2015 +1850 + diff --git a/cime_config/buildnml b/cime_config/buildnml index 9c156b66d5..674d1a29ea 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -48,12 +48,6 @@ def buildnml(case, caseroot, compname): RUN_REFTOD = case.get_value("RUN_REFTOD") COMP_INTERFACE = case.get_value("COMP_INTERFACE") - stream_ndep_year_first = case.get_value("CAM_STREAM_NDEP_YEAR_FIRST") - stream_ndep_year_last = case.get_value("CAM_STREAM_NDEP_YEAR_LAST") - stream_ndep_year_align = case.get_value("CAM_STREAM_NDEP_YEAR_ALIGN") - stream_ndep_data_filename = case.get_value("CAM_STREAM_NDEP_DATA_FILENAME") - stream_ndep_mesh_filename = case.get_value("CAM_STREAM_NDEP_MESH_FILENAME") - testsrc = os.path.join(srcroot, "components", "cam") if os.path.exists(testsrc): srcroot = testsrc @@ -173,12 +167,6 @@ def buildnml(case, caseroot, compname): buildnl_opts += ["-inputdata", input_data_list] - CAM_NAMELIST_OPTS += " stream_ndep_year_first=" + stream_ndep_year_first - CAM_NAMELIST_OPTS += " stream_ndep_year_last=" + stream_ndep_year_last - CAM_NAMELIST_OPTS += " stream_ndep_year_align=" + stream_ndep_year_align - CAM_NAMELIST_OPTS += " stream_ndep_data_filename='" + stream_ndep_data_filename.strip() + "'" - CAM_NAMELIST_OPTS += " stream_ndep_mesh_filename='" + stream_ndep_mesh_filename.strip() + "'" - buildnl_opts += ["-namelist", '" &atmexp ' + CAM_NAMELIST_OPTS + '/" '] diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 2ab0a50558..ef718404f5 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -383,79 +383,6 @@ User mods to apply to specific compset matches. - - - - char - 2000 - - 1850 - 2010 - 1850 - 2015 - - run_component_cam - env_run.xml - Nitrogen deposition data year first - - - - char - 2000 - - 2010 - 1850 - 2015 - 2101 - - run_component_cam - env_run.xml - Nitrogen deposition data year last - - - - char - 1 - - 1850 - 2015 - - run_component_cam - env_run.xml - Nitrogen deposition align CAM_STREAM_NDEP_YEAR_FIRST with this model year - - - - - char - UNSET - - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc - $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc - - run_component_cam - env_run.xml - Nitrogen deposition data filename - - - - char - $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc - run_component_cam - env_run.xml - Nitrogen deposition mesh filename (corresponding to the CAM_STREAM_NDEP_DATA_FILENAME) - - ========================================= CAM naming conventions diff --git a/src/chemistry/mozart/chemistry.F90 b/src/chemistry/mozart/chemistry.F90 index 085bd2237b..6527b0ccc1 100644 --- a/src/chemistry/mozart/chemistry.F90 +++ b/src/chemistry/mozart/chemistry.F90 @@ -24,6 +24,7 @@ module chemistry use ref_pres, only : ptop_ref use phys_control, only : waccmx_is ! WACCM-X switch query function use phys_control, only : use_hemco ! HEMCO switch logical + use mo_chm_diags, only : chem_has_ndep_flx => chm_prod_ndep_flx implicit none private @@ -46,6 +47,7 @@ module chemistry public :: chem_read_restart public :: chem_init_restart public :: chem_emissions + public :: chem_has_ndep_flx integer, public :: imozart = -1 ! index of 1st constituent @@ -1147,6 +1149,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o) use mo_neu_wetdep, only : neu_wetdep_tend use aerodep_flx, only : aerodep_flx_prescribed use short_lived_species, only : short_lived_species_writeic + use atm_stream_ndep, only : ndep_stream_active implicit none @@ -1265,11 +1268,13 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o) cam_out%precc, cam_out%precl, cam_in%snowhland, ghg_chem, state%latmapback, & drydepflx, wetdepflx, cam_in%cflx, cam_in%fireflx, cam_in%fireztop, & nhx_nitrogen_flx, noy_nitrogen_flx, use_hemco, ptend%q, pbuf ) - if (associated(cam_out%nhx_nitrogen_flx)) then - cam_out%nhx_nitrogen_flx(:ncol) = nhx_nitrogen_flx(:ncol) - endif - if (associated(cam_out%noy_nitrogen_flx)) then - cam_out%noy_nitrogen_flx(:ncol) = noy_nitrogen_flx(:ncol) + if (.not.ndep_stream_active) then + if (associated(cam_out%nhx_nitrogen_flx)) then + cam_out%nhx_nitrogen_flx(:ncol) = nhx_nitrogen_flx(:ncol) + endif + if (associated(cam_out%noy_nitrogen_flx)) then + cam_out%noy_nitrogen_flx(:ncol) = noy_nitrogen_flx(:ncol) + endif endif call t_stopf( 'chemdr' ) diff --git a/src/chemistry/mozart/mo_chm_diags.F90 b/src/chemistry/mozart/mo_chm_diags.F90 index 5650403fee..1a11b2b39d 100644 --- a/src/chemistry/mozart/mo_chm_diags.F90 +++ b/src/chemistry/mozart/mo_chm_diags.F90 @@ -18,6 +18,7 @@ module mo_chm_diags public :: chm_diags_inti public :: chm_diags public :: het_diags + public :: chm_prod_ndep_flx integer :: id_n,id_no,id_no2,id_no3,id_n2o5,id_hno3,id_ho2no2,id_clono2,id_brono2 integer :: id_isopfdn, id_isopfdnc, id_terpfdn !these are dinitrates @@ -55,6 +56,8 @@ module mo_chm_diags real(r8), parameter :: N_molwgt = 14.00674_r8 real(r8), parameter :: S_molwgt = 32.066_r8 + logical, protected :: chm_prod_ndep_flx =.false. + contains subroutine chm_diags_inti @@ -330,6 +333,8 @@ subroutine chm_diags_inti toth_species = (/ id_ch4, id_h2o, id_h2 /) + chm_prod_ndep_flx = any(noy_species>0) .or. any(nhx_species>0) + call addfld( 'NOX', (/ 'lev' /), 'A', 'mol/mol', 'nox (N+NO+NO2)' ) call addfld( 'NOY', (/ 'lev' /), 'A', 'mol/mol', & 'noy = total nitrogen (N+NO+NO2+NO3+2N2O5+HNO3+HO2NO2+ORGNOY+NH4NO3)' ) diff --git a/src/chemistry/pp_none/chemistry.F90 b/src/chemistry/pp_none/chemistry.F90 index 7e67fadb6e..9da9aa0852 100644 --- a/src/chemistry/pp_none/chemistry.F90 +++ b/src/chemistry/pp_none/chemistry.F90 @@ -7,7 +7,7 @@ module chemistry use shr_kind_mod, only: r8 => shr_kind_r8 use physics_types, only: physics_state, physics_ptend use ppgrid, only: begchunk, endchunk, pcols - + implicit none private @@ -27,9 +27,10 @@ module chemistry public :: chem_write_restart public :: chem_read_restart public :: chem_init_restart - public :: chem_readnl ! read chem namelist + public :: chem_readnl ! read chem namelist public :: chem_reset_fluxes public :: chem_emissions + public :: chem_has_ndep_flx interface chem_write_restart module procedure chem_write_restart_bin @@ -40,6 +41,8 @@ module chemistry module procedure chem_read_restart_pio end interface + logical, parameter :: chem_has_ndep_flx = .false. + ! Private data !================================================================================================ @@ -61,10 +64,10 @@ end function chem_is subroutine chem_register use aero_model, only : aero_model_register - !----------------------------------------------------------------------- - ! + !----------------------------------------------------------------------- + ! ! Purpose: register advected constituents for parameterized greenhouse gas chemistry - ! + ! !----------------------------------------------------------------------- ! for prescribed aerosols @@ -95,12 +98,12 @@ end function chem_is_active !================================================================================================ function chem_implements_cnst(name) - !----------------------------------------------------------------------- - ! + !----------------------------------------------------------------------- + ! ! Purpose: return true if specified constituent is implemented by this package - ! + ! ! Author: B. Eaton - ! + ! !----------------------------------------------------------------------- implicit none !-----------------------------Arguments--------------------------------- @@ -115,11 +118,11 @@ end function chem_implements_cnst !=============================================================================== subroutine chem_init(phys_state, pbuf2d) - !----------------------------------------------------------------------- - ! + !----------------------------------------------------------------------- + ! ! Purpose: initialize parameterized greenhouse gas chemistry ! (declare history variables) - ! + ! !----------------------------------------------------------------------- use physics_buffer, only : physics_buffer_desc use aero_model, only : aero_model_init @@ -138,7 +141,7 @@ subroutine chem_timestep_init(phys_state, pbuf2d) use physics_buffer, only : physics_buffer_desc use time_manager, only: get_curr_date, get_perp_date, get_curr_calday, & is_perpetual - type(physics_state), intent(in):: phys_state(begchunk:endchunk) + type(physics_state), intent(in):: phys_state(begchunk:endchunk) type(physics_buffer_desc), pointer :: pbuf2d(:,:) @@ -162,7 +165,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o) type(cam_out_t), intent(in) :: cam_out type(physics_buffer_desc), pointer :: pbuf(:) real(r8), optional, intent(out) :: fh2o(pcols) ! h2o flux to balance source from chemistry - + return end subroutine chem_timestep_tend @@ -215,7 +218,7 @@ subroutine chem_init_restart(File) end subroutine chem_init_restart !================================================================================ subroutine chem_reset_fluxes( fptr, cam_in ) - use camsrfexch, only : cam_in_t + use camsrfexch, only : cam_in_t real(r8), pointer :: fptr(:,:) ! pointer into array data type(cam_in_t), intent(inout) :: cam_in(begchunk:endchunk) @@ -223,7 +226,7 @@ subroutine chem_reset_fluxes( fptr, cam_in ) end subroutine chem_reset_fluxes !================================================================================ subroutine chem_emissions( state, cam_in, pbuf ) - use camsrfexch, only: cam_in_t + use camsrfexch, only: cam_in_t use physics_buffer, only: physics_buffer_desc ! Arguments: diff --git a/src/control/camsrfexch.F90 b/src/control/camsrfexch.F90 index 0357ba3128..8111785cd1 100644 --- a/src/control/camsrfexch.F90 +++ b/src/control/camsrfexch.F90 @@ -9,14 +9,12 @@ module camsrfexch use constituents, only: pcnst use ppgrid, only: pcols, begchunk, endchunk use phys_grid, only: get_ncols_p, phys_grid_initialized - use infnan, only: posinf, assignment(=) + use infnan, only: nan, posinf, assignment(=) use cam_abortutils, only: endrun use cam_logfile, only: iulog use srf_field_check, only: active_Sl_ram1, active_Sl_fv, active_Sl_soilw, & - active_Fall_flxdst1, active_Fall_flxvoc, active_Fall_flxfire, & - active_Faxa_nhx, active_Faxa_noy - - + active_Fall_flxdst1, active_Fall_flxvoc, active_Fall_flxfire + use cam_control_mod, only: aqua_planet, simple_phys implicit none private @@ -100,7 +98,7 @@ module camsrfexch real(r8) :: tref(pcols) ! ref height surface air temp real(r8) :: qref(pcols) ! ref height specific humidity real(r8) :: u10(pcols) ! 10m wind speed - real(r8) :: ugustOut(pcols) ! gustiness added + real(r8) :: ugustOut(pcols) ! gustiness added real(r8) :: u10withGusts(pcols) ! 10m wind speed with gusts added real(r8) :: ts(pcols) ! merged surface temp real(r8) :: sst(pcols) ! sea surface temp @@ -325,14 +323,20 @@ subroutine atm2hub_alloc( cam_out ) cam_out(c)%dstwet4(:) = 0._r8 nullify(cam_out(c)%nhx_nitrogen_flx) - allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror) - if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx') - cam_out(c)%nhx_nitrogen_flx(:) = 0._r8 - nullify(cam_out(c)%noy_nitrogen_flx) - allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror) - if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx') - cam_out(c)%noy_nitrogen_flx(:) = 0._r8 + + if (.not.(simple_phys .or. aqua_planet)) then + + allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror) + if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx') + cam_out(c)%nhx_nitrogen_flx(:) = nan + + allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror) + if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx') + cam_out(c)%noy_nitrogen_flx(:) = nan + + endif + end do end subroutine atm2hub_alloc diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 915664cdb9..f7bc2a40ff 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -102,6 +102,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use cam_budget, only: cam_budget_readnl use phys_grid_ctem, only: phys_grid_ctem_readnl use mo_lightning, only: lightning_readnl + use atm_stream_ndep, only: stream_ndep_readnl !---------------------------Arguments----------------------------------- @@ -205,6 +206,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call hemco_readnl(nlfilename) call cam_budget_readnl(nlfilename) call phys_grid_ctem_readnl(nlfilename) + call stream_ndep_readnl(nlfilename) end subroutine read_namelist diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index b3e16bee8c..b5b56b8112 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -22,10 +22,10 @@ module atm_import_export use srf_field_check , only : set_active_Fall_flxfire use srf_field_check , only : set_active_Fall_fco2_lnd use srf_field_check , only : set_active_Faoo_fco2_ocn - use srf_field_check , only : set_active_Faxa_nhx - use srf_field_check , only : set_active_Faxa_noy - use srf_field_check , only : active_Faxa_nhx, active_Faxa_noy - use atm_stream_ndep , only : stream_ndep_init, stream_ndep_interp, stream_ndep_is_initialized, use_ndep_stream + use atm_stream_ndep , only : stream_ndep_init, stream_ndep_interp, stream_ndep_is_initialized + use atm_stream_ndep , only : ndep_stream_active + use chemistry , only : chem_has_ndep_flx + use cam_control_mod , only : aqua_planet, simple_phys implicit none private ! except @@ -60,7 +60,6 @@ module atm_import_export integer :: drydep_nflds = -huge(1) ! number of dry deposition velocity fields lnd-> atm integer :: megan_nflds = -huge(1) ! number of MEGAN voc fields from lnd-> atm integer :: emis_nflds = -huge(1) ! number of fire emission fields from lnd-> atm - integer, public :: ndep_nflds = -huge(1) ! number of nitrogen deposition fields from atm->lnd/ocn logical :: atm_provides_lightning = .false. ! cld to grnd lightning flash freq (min-1) character(*),parameter :: F01 = "('(cam_import_export) ',a,i8,2x,i8,2x,d21.14)" character(*),parameter :: F02 = "('(cam_import_export) ',a,i8,2x,i8,2x,i8,2x,d21.14)" @@ -79,13 +78,11 @@ subroutine read_surface_fields_namelists() use shr_megan_mod , only : shr_megan_readnl use shr_fire_emis_mod , only : shr_fire_emis_readnl use shr_carma_mod , only : shr_carma_readnl - use shr_ndep_mod , only : shr_ndep_readnl use shr_lightning_coupling_mod, only : shr_lightning_coupling_readnl character(len=*), parameter :: nl_file_name = 'drv_flds_in' ! read mediator fields options - call shr_ndep_readnl(nl_file_name, ndep_nflds) call shr_drydep_readnl(nl_file_name, drydep_nflds) call shr_megan_readnl(nl_file_name, megan_nflds) call shr_fire_emis_readnl(nl_file_name, emis_nflds) @@ -194,16 +191,7 @@ subroutine advertise_fields(gcomp, flds_scalar_name, rc) call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Sa_co2diag' ) end if - if (ndep_nflds > 0) then - ! The following is when CAM/WACCM computes ndep - call set_active_Faxa_nhx(.true.) - call set_active_Faxa_noy(.true.) - else - ! The following is used for reading in stream data, or for aquaplanet or simple model - ! cases where the ndep fluxes are not used. - call set_active_Faxa_nhx(.false.) - call set_active_Faxa_noy(.false.) - end if + ! Nitrogen deposition fluxes ! Assume that 2 fields are always sent as part of Faxa_ndep call fldlist_add(fldsFrAtm_num, fldsFrAtm, 'Faxa_ndep', ungridded_lbound=1, ungridded_ubound=2) @@ -1121,10 +1109,8 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) call state_getfldptr(exportState, 'Faxa_ndep', fldptr2d=fldptr_ndep, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (.not. active_Faxa_nhx .and. .not. active_Faxa_noy) then - ! ndep fields not active (i.e., not computed by WACCM). Either they are not needed, - ! or they are obtained from the ndep input stream. + if (.not. (simple_phys .or. aqua_planet)) then ! The ndep_stream_nl namelist group is read in stream_ndep_init. This sets whether ! or not the stream will be used. @@ -1134,45 +1120,43 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) stream_ndep_is_initialized = .true. end if - if (use_ndep_stream) then + if (ndep_stream_active.or.chem_has_ndep_flx) then + ! Nitrogen dep fluxes are obtained from the ndep input stream if input data is available + ! otherwise computed by chemistry + if (ndep_stream_active) then + + ! get ndep fluxes from the stream + call stream_ndep_interp(cam_out, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! NDEP read from forcing is expected to be in units of gN/m2/sec - but the mediator + ! expects units of kgN/m2/sec + scale_ndep = .001_r8 + + else if (chem_has_ndep_flx) then - ! get ndep fluxes from the stream - call stream_ndep_interp(cam_out, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - ! NDEP read from forcing is expected to be in units of gN/m2/sec - but the mediator - ! expects units of kgN/m2/sec - scale_ndep = .001_r8 + ! Assume chemistry computes ndep fluxes, then its in units of kgN/m2/s - and the mediator expects + ! units of kgN/m2/sec, so the following conversion needs to happen + scale_ndep = 1._r8 - else + end if - ! ndep fluxes not used. Set to zero. + g = 1 do c = begchunk,endchunk do i = 1,get_ncols_p(c) - cam_out(c)%nhx_nitrogen_flx(i) = 0._r8 - cam_out(c)%noy_nitrogen_flx(i) = 0._r8 + fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) + fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) + g = g + 1 end do end do - scale_ndep = 1._r8 - end if + else - else + fldptr_ndep(:,:) = 0._r8 - ! If waccm computes ndep, then its in units of kgN/m2/s - and the mediator expects - ! units of kgN/m2/sec, so the following conversion needs to happen - scale_ndep = 1._r8 + end if end if - g = 1 - do c = begchunk,endchunk - do i = 1,get_ncols_p(c) - fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) - fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) - g = g + 1 - end do - end do - end subroutine export_fields !=============================================================================== diff --git a/src/cpl/nuopc/atm_stream_ndep.F90 b/src/cpl/nuopc/atm_stream_ndep.F90 index a393b27f05..eed6ac619e 100644 --- a/src/cpl/nuopc/atm_stream_ndep.F90 +++ b/src/cpl/nuopc/atm_stream_ndep.F90 @@ -21,52 +21,46 @@ module atm_stream_ndep implicit none private + public :: stream_ndep_readnl ! read runtime options public :: stream_ndep_init ! position datasets for dynamic ndep public :: stream_ndep_interp ! interpolates between two years of ndep file data private :: stream_ndep_check_units ! Check the units and make sure they can be used ! The ndep stream is not needed for aquaplanet or simple model configurations. It - ! is disabled by setting the namelist variable stream_ndep_data_filename to blank. - logical, public, protected :: use_ndep_stream = .true. + ! is disabled by setting the namelist variable stream_ndep_data_filename to 'UNSET' or empty string. + logical, public, protected :: ndep_stream_active = .false. type(shr_strdata_type) :: sdat_ndep ! input data stream logical, public :: stream_ndep_is_initialized = .false. character(len=CS) :: stream_varlist_ndep(2) type(ESMF_Clock) :: model_clock - character(len=*), parameter :: sourcefile = & - __FILE__ + character(len=*), parameter :: sourcefile = __FILE__ + + character(len=CL) :: stream_ndep_data_filename + character(len=CL) :: stream_ndep_mesh_filename + integer :: stream_ndep_year_first ! first year in stream to use + integer :: stream_ndep_year_last ! last year in stream to use + integer :: stream_ndep_year_align ! align stream_year_firstndep with !============================================================================== contains !============================================================================== - subroutine stream_ndep_init(model_mesh, model_clock, rc) - ! - ! Initialize data stream information. + subroutine stream_ndep_readnl(nlfile) ! Uses: - use cam_instance , only: inst_suffix - use shr_nl_mod , only: shr_nl_find_group_name - use dshr_strdata_mod , only: shr_strdata_init_from_inline + use shr_nl_mod, only: shr_nl_find_group_name ! input/output variables - type(ESMF_CLock), intent(in) :: model_clock - type(ESMF_Mesh) , intent(in) :: model_mesh - integer , intent(out) :: rc + character(len=*), intent(in) :: nlfile ! local variables integer :: nu_nml ! unit for namelist file integer :: nml_error ! namelist i/o error flag - character(len=CL) :: stream_ndep_data_filename - character(len=CL) :: stream_ndep_mesh_filename - character(len=CL) :: filein ! atm namelist file - integer :: stream_ndep_year_first ! first year in stream to use - integer :: stream_ndep_year_last ! last year in stream to use - integer :: stream_ndep_year_align ! align stream_year_firstndep with integer :: ierr - character(*), parameter :: subName = "('stream_ndep_init')" + character(*), parameter :: subName = "('stream_ndep_readnl')" !----------------------------------------------------------------------- namelist /ndep_stream_nl/ & @@ -76,8 +70,6 @@ subroutine stream_ndep_init(model_mesh, model_clock, rc) stream_ndep_year_last, & stream_ndep_year_align - rc = ESMF_SUCCESS - ! Default values for namelist stream_ndep_data_filename = ' ' stream_ndep_mesh_filename = ' ' @@ -90,10 +82,9 @@ subroutine stream_ndep_init(model_mesh, model_clock, rc) ! Read ndep_stream namelist if (masterproc) then - filein = "atm_in" // trim(inst_suffix) - open( newunit=nu_nml, file=trim(filein), status='old', iostat=nml_error ) + open( newunit=nu_nml, file=trim(nlfile), status='old', iostat=nml_error ) if (nml_error /= 0) then - call endrun(subName//': ERROR opening '//trim(filein)//errMsg(sourcefile, __LINE__)) + call endrun(subName//': ERROR opening '//trim(nlfile)//errMsg(sourcefile, __LINE__)) end if call shr_nl_find_group_name(nu_nml, 'ndep_stream_nl', status=nml_error) if (nml_error == 0) then @@ -101,8 +92,6 @@ subroutine stream_ndep_init(model_mesh, model_clock, rc) if (nml_error /= 0) then call endrun(' ERROR reading ndep_stream_nl namelist'//errMsg(sourcefile, __LINE__)) end if - else - call endrun(' ERROR finding ndep_stream_nl namelist'//errMsg(sourcefile, __LINE__)) end if close(nu_nml) endif @@ -117,9 +106,10 @@ subroutine stream_ndep_init(model_mesh, model_clock, rc) call mpi_bcast(stream_ndep_year_align, 1, mpi_integer, 0, mpicom, ierr) if (ierr /= 0) call endrun(trim(subname)//": FATAL: mpi_bcast: stream_ndep_year_align") + ndep_stream_active = len_trim(stream_ndep_data_filename)>0 .and. stream_ndep_data_filename/='UNSET' + ! Check whether the stream is being used. - if (stream_ndep_data_filename == ' '.or.stream_ndep_data_filename == 'UNSET') then - use_ndep_stream = .false. + if (.not.ndep_stream_active) then if (masterproc) then write(iulog,'(a)') ' ' write(iulog,'(a)') 'NDEP STREAM IS NOT USED.' @@ -140,6 +130,25 @@ subroutine stream_ndep_init(model_mesh, model_clock, rc) write(iulog,'(a)' ) ' ' endif + end subroutine stream_ndep_readnl + + subroutine stream_ndep_init(model_mesh, model_clock, rc) + use dshr_strdata_mod, only: shr_strdata_init_from_inline + + ! input/output variables + type(ESMF_CLock), intent(in) :: model_clock + type(ESMF_Mesh) , intent(in) :: model_mesh + integer , intent(out) :: rc + + ! local variables + character(*), parameter :: subName = "('stream_ndep_init')" + + rc = ESMF_SUCCESS + if (.not.ndep_stream_active) then + return + end if + ! + ! Initialize data stream information. ! Read in units call stream_ndep_check_units(stream_ndep_data_filename) diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 97dad2ba01..3a01d9536e 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -568,6 +568,9 @@ subroutine diag_init_moist(pbuf2d) call addfld('a2x_DSTWET4', horiz_only, 'A', 'kg/m2/s', 'wetdep of dust (bin4)') call addfld('a2x_DSTDRY4', horiz_only, 'A', 'kg/m2/s', 'drydep of dust (bin4)') + call addfld('a2x_NOYDEP', horiz_only, 'A', 'kg/m2/s', 'NOy Deposition Flux') + call addfld('a2x_NHXDEP', horiz_only, 'A', 'kg/m2/s', 'NHx Deposition Flux') + ! defaults if (history_amwg) then call add_default (cnst_name(1), 1, ' ') @@ -1903,6 +1906,13 @@ subroutine diag_export(cam_out) call outfld('a2x_DSTDRY4', cam_out%dstdry4, pcols, lchnk) end if + if (associated(cam_out%nhx_nitrogen_flx)) then + call outfld('a2x_NHXDEP', cam_out%nhx_nitrogen_flx, pcols, lchnk) + end if + if (associated(cam_out%noy_nitrogen_flx)) then + call outfld('a2x_NOYDEP', cam_out%noy_nitrogen_flx, pcols, lchnk) + end if + end subroutine diag_export !####################################################################### diff --git a/src/utils/srf_field_check.F90 b/src/utils/srf_field_check.F90 index d1c0adfbca..a0aa0cb0f5 100644 --- a/src/utils/srf_field_check.F90 +++ b/src/utils/srf_field_check.F90 @@ -29,8 +29,6 @@ module srf_field_check public :: set_active_Fall_flxfire public :: set_active_Fall_fco2_lnd public :: set_active_Faoo_fco2_ocn - public :: set_active_Faxa_nhx - public :: set_active_Faxa_noy !=============================================================================== contains @@ -76,14 +74,4 @@ subroutine set_active_Faoo_fco2_ocn(is_active) active_Faoo_fco2_ocn = is_active end subroutine set_active_Faoo_fco2_ocn - subroutine set_active_Faxa_nhx(is_active) - logical, intent(in) :: is_active - active_Faxa_nhx = is_active - end subroutine set_active_Faxa_nhx - - subroutine set_active_Faxa_noy(is_active) - logical, intent(in) :: is_active - active_Faxa_noy = is_active - end subroutine set_active_Faxa_noy - end module srf_field_check From d1736fce0e0f50400d45d66c36db01ac6e1a3ea5 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Thu, 12 Dec 2024 11:36:44 -0500 Subject: [PATCH 53/89] add ozone for hightop aquaplanet configs --- bld/namelist_files/use_cases/aquaplanet_cam7.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bld/namelist_files/use_cases/aquaplanet_cam7.xml b/bld/namelist_files/use_cases/aquaplanet_cam7.xml index 405e14bbe0..efbfff14b1 100644 --- a/bld/namelist_files/use_cases/aquaplanet_cam7.xml +++ b/bld/namelist_files/use_cases/aquaplanet_cam7.xml @@ -26,7 +26,8 @@ atm/cam/solar/ape_solar_ave_tsi_1365.nc -apeozone_cam3_5_54.nc +apeozone_cam3_5_54.nc +aquaplanet_ozone_hightop_c20180412.nc atm/cam/ozone OZONE CYCLICAL From b70cfeaf6a2e6aa3511cc469a53d8de080b112c3 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 19 Dec 2024 13:24:28 -0700 Subject: [PATCH 54/89] fix some issues in derecho regression tests modified: bld/build-namelist modified: bld/namelist_files/namelist_defaults_cam.xml modified: bld/namelist_files/namelist_definition.xml modified: bld/namelist_files/use_cases/2010_cam6.xml modified: bld/namelist_files/use_cases/sd_cam6.xml modified: bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml modified: src/chemistry/geoschem/chemistry.F90 modified: src/chemistry/pp_terminator/chemistry.F90 modified: src/control/camsrfexch.F90 --- bld/build-namelist | 13 +++++ bld/namelist_files/namelist_defaults_cam.xml | 3 ++ bld/namelist_files/namelist_definition.xml | 6 +++ bld/namelist_files/use_cases/2010_cam6.xml | 4 ++ bld/namelist_files/use_cases/sd_cam6.xml | 6 ++- .../use_cases/waccm_sc_1850_cam6.xml | 7 +++ src/chemistry/geoschem/chemistry.F90 | 31 ++++++------ src/chemistry/pp_terminator/chemistry.F90 | 49 ++++++++++--------- src/control/camsrfexch.F90 | 6 +-- 9 files changed, 84 insertions(+), 41 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index 6dd96595d9..22be75b310 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -509,6 +509,19 @@ if ($phys_mode_flags > 1) { my $simple_phys = 0; if ($adia_mode or $ideal_mode) { $simple_phys = 1; } +# Setup default ndep streams only if not simple_phys or aqua_mode and +# the chemistry cannot produce the nitrogen depostion fluxes +if (!($simple_phys or $aqua_mode)) { + my $chem_nitrodep = chem_has_species($cfg, 'NO') and chem_has_species($cfg, 'NH3'); + if (!$chem_nitrodep) { + add_default($nl, 'stream_ndep_data_filename'); + add_default($nl, 'stream_ndep_mesh_filename'); + add_default($nl, 'stream_ndep_year_first'); + add_default($nl, 'stream_ndep_year_last'); + add_default($nl, 'stream_ndep_year_align'); + } +} + # Single column mode my $scam = $cfg->get('scam'); my $scam_iop = $cfg->get('scam_iop'); diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index ab2707290c..501047a1bc 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2063,6 +2063,9 @@ lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +1850 +2015 +1850 2000 2000 1 diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 4aaa038224..185edfa81e 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -7609,6 +7609,12 @@ Bubble-mediated sea-air transfer. See ocean_emis.F90 for details. Default: FALSE + +List of nitrogen deposition fluxes to be sent from CAM to surface models. +Default: set by build-namelist. + + Year first to use in nitrogen deposition stream data. diff --git a/bld/namelist_files/use_cases/2010_cam6.xml b/bld/namelist_files/use_cases/2010_cam6.xml index 239f5436f6..d392d2b76e 100644 --- a/bld/namelist_files/use_cases/2010_cam6.xml +++ b/bld/namelist_files/use_cases/2010_cam6.xml @@ -83,4 +83,8 @@ 'CYCLICAL' 2010 +2010 +2010 +1 + diff --git a/bld/namelist_files/use_cases/sd_cam6.xml b/bld/namelist_files/use_cases/sd_cam6.xml index 146268c62b..9a89255e88 100644 --- a/bld/namelist_files/use_cases/sd_cam6.xml +++ b/bld/namelist_files/use_cases/sd_cam6.xml @@ -28,7 +28,7 @@ 'SERIAL' 'atm/cam/ozone_strataero' - 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc' + 'ozone_strataero_WACCM_L70_zm5day_18500101-20150103_CMIP6ensAvg_c180923.nc' .true. 'CHEM_LBC_FILE' @@ -36,4 +36,8 @@ 'SERIAL' 'CO2','CH4','N2O','CFC11eq','CFC12' + 1850 + 2015 + 1850 + diff --git a/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml b/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml index dbc6b0921b..691150a417 100644 --- a/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml @@ -88,4 +88,11 @@ 'UTEND4', 'UTEND5', 'FRONTGF', 'FRONTGFA', 'EKGW', 'QNO', 'QRLNLTE', 'QRL_TOT', 'DUV', 'DVV', 'TTPXMLC' + +lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc +share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc +1850 +1850 +1 + diff --git a/src/chemistry/geoschem/chemistry.F90 b/src/chemistry/geoschem/chemistry.F90 index fbb99e4b8f..e46bda2c4e 100644 --- a/src/chemistry/geoschem/chemistry.F90 +++ b/src/chemistry/geoschem/chemistry.F90 @@ -22,7 +22,7 @@ module chemistry #if defined( MODAL_AERO ) use modal_aero_data, only : ntot_amode #endif - + ! GEOS-Chem derived types USE DiagList_Mod, ONLY : DgnList ! Diagnostics list object use GeosChem_History_Mod, ONLY : HistoryConfigObj ! History diagnostic object @@ -59,6 +59,7 @@ module chemistry public :: chem_readnl ! read chem namelist public :: chem_emissions public :: chem_timestep_init + public :: chem_has_ndep_flx ! ! Private routines: @@ -166,6 +167,8 @@ module chemistry ! For dry deposition character(len=shr_kind_cl) :: depvel_lnd_file = 'depvel_lnd_file' + ! for nitrogen deposition fluxes to surface models + logical, parameter :: chem_has_ndep_flx = .false. contains @@ -515,11 +518,11 @@ subroutine chem_register CALL cnst_get_ind('Q', cQ, abort=.True.) CALL cnst_get_ind('H2O', cH2O, abort=.True.) CALL cnst_get_ind('H2SO4', cH2SO4, abort=.True.) - + !------------------------------------------------------------ ! Get mapping between dry deposition species and species set !------------------------------------------------------------ - + nIgnored = 0 if (debug .and. masterproc) write(iulog,'(a,i4,a)') 'chem_register: looping over gas dry deposition list with ', nddvels, ' species' @@ -831,7 +834,7 @@ subroutine chem_readnl(nlfile) ! Now go through the KPP mechanism and add any species not ! implemented by the tracer list in geoschem_config.yml !---------------------------------------------------------- - + IF ( nSpec > nSlsMax ) THEN CALL ENDRUN('chem_readnl: too many species - increase nSlsmax') ENDIF @@ -1022,7 +1025,7 @@ subroutine chem_init(phys_state, pbuf2d) use Time_Mod, only : Accept_External_Date_Time use Ucx_Mod, only : Init_Ucx use Unitconv_Mod, only : MOLES_SPECIES_PER_MOLES_DRY_AIR - use Vdiff_Mod, only : Max_PblHt_For_Vdiff + use Vdiff_Mod, only : Max_PblHt_For_Vdiff TYPE(physics_state), INTENT(IN ) :: phys_state(BEGCHUNK:ENDCHUNK) TYPE(physics_buffer_desc), POINTER, INTENT(INOUT) :: pbuf2d(:,:) @@ -1143,7 +1146,7 @@ subroutine chem_init(phys_state, pbuf2d) ! on State_Grid(BEGCHUNK). ! To go around this, we define all of GEOS-Chem arrays with ! size PCOLS x PVER, which is the largest possible number of - ! grid cells. + ! grid cells. CALL Init_State_Grid( Input_Opt = Input_Opt, & State_Grid = maxGrid, & RC = RC ) @@ -1484,7 +1487,7 @@ subroutine chem_init(phys_state, pbuf2d) ! Init_Drydep ! Thibaud M. Fritz - 04 Mar 2020 !---------------------------------------------------------- - + ALLOCATE(map2GC_dryDep(nddvels), STAT=IERR) IF ( IERR .NE. 0 ) CALL ENDRUN('Failed to allocate map2GC_dryDep') @@ -1754,7 +1757,7 @@ subroutine chem_timestep_init(phys_state, pbuf2d) use mo_flbc, only : flbc_chk use mo_ghg_chem, only : ghg_chem_timestep_init use physics_buffer, only : physics_buffer_desc - + TYPE(physics_state), INTENT(IN):: phys_state(begchunk:endchunk) TYPE(physics_buffer_desc), POINTER :: pbuf2d(:,:) @@ -2019,7 +2022,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dT, pbuf, fh2o ) REAL(r8) :: mmr_tend(state%NCOL,PVER,gas_pcnst) REAL(r8) :: wk_out(state%NCOL) LOGICAL :: Found - + CHARACTER(LEN=shr_kind_cl) :: tagName REAL(r8), PARAMETER :: zlnd = 0.01_r8 ! Roughness length for soil [m] @@ -2364,7 +2367,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dT, pbuf, fh2o ) ENDDO ! Deal with secondary organic aerosols (SOAs). This mapping is using the - ! complex SOA option in GEOS-Chem. + ! complex SOA option in GEOS-Chem. ! MAM uses five volatility bins spanning saturation concentrations from 0.01 ! to 100 ug/m3 (logarithmically). The complex SOA option has four volatility ! bins that 0.1 to 100 ug/m3. We lump the lowest two bins in CESM2 to the @@ -3692,7 +3695,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dT, pbuf, fh2o ) ! Compute the surface flux for the non-local mixing, ! (which means getting emissions & drydep from HEMCO) ! and store it in State_Chm%Surface_Flux - ! + ! ! For CESM-GC, Surface_Flux will be equal to the opposite of the ! dry deposition flux since emissions are loaded externally ! ( SurfaceFlux = eflx - dflx = - dflx ) @@ -3739,10 +3742,10 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dT, pbuf, fh2o ) ! Get the species ID from the drydep ID N = State_Chm(BEGCHUNK)%Map_DryDep(ND) IF ( N <= 0 ) CYCLE - + M = map2GCinv(N) IF ( M <= 0 ) CYCLE - + cam_in%cflx(1:nY,M) = cam_in%cflx(1:nY,M) & + State_Chm(LCHNK)%SurfaceFlux(1,1:nY,N) ENDDO @@ -3763,7 +3766,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dT, pbuf, fh2o ) new_units = KG_SPECIES_PER_M2, & previous_units = previous_units, & RC = RC ) - + IF ( RC /= GC_SUCCESS ) THEN ErrMsg = 'Error encountered in "Convert_Spc_Units"!' diff --git a/src/chemistry/pp_terminator/chemistry.F90 b/src/chemistry/pp_terminator/chemistry.F90 index 11fbf5e0c9..b1e82d8d65 100644 --- a/src/chemistry/pp_terminator/chemistry.F90 +++ b/src/chemistry/pp_terminator/chemistry.F90 @@ -32,9 +32,10 @@ module chemistry public :: chem_write_restart public :: chem_read_restart public :: chem_init_restart - public :: chem_readnl ! read chem namelist + public :: chem_readnl ! read chem namelist public :: chem_reset_fluxes public :: chem_emissions + public :: chem_has_ndep_flx interface chem_write_restart module procedure chem_write_restart_bin @@ -45,9 +46,11 @@ module chemistry module procedure chem_read_restart_pio end interface + logical, parameter :: chem_has_ndep_flx = .false. + ! Private data integer, parameter :: nspecies = 3 - + integer :: idx_cl =-1 integer :: idx_cl2=-1 @@ -75,10 +78,10 @@ end function chem_is !================================================================================================ subroutine chem_register - !----------------------------------------------------------------------- - ! + !----------------------------------------------------------------------- + ! ! Purpose: register advected constituents for parameterized greenhouse gas chemistry - ! + ! !----------------------------------------------------------------------- real(r8), parameter :: cptmp = 666._r8 @@ -86,10 +89,10 @@ subroutine chem_register logical :: camout integer :: i, n - + do i = 1, nspecies camout = trim(species(i)) .eq. 'RHO' - call cnst_add( species(i), adv_mass(i), cptmp, qmin, n, & + call cnst_add( species(i), adv_mass(i), cptmp, qmin, n, & readiv=.true.,mixtype='dry',cam_outfld=camout) indices(i) = n map2chm(n) = i @@ -123,12 +126,12 @@ end function chem_is_active !================================================================================================ function chem_implements_cnst(name) - !----------------------------------------------------------------------- - ! + !----------------------------------------------------------------------- + ! ! Purpose: return true if specified constituent is implemented by this package - ! + ! ! Author: B. Eaton - ! + ! !----------------------------------------------------------------------- implicit none !-----------------------------Arguments--------------------------------- @@ -137,7 +140,7 @@ function chem_implements_cnst(name) logical :: chem_implements_cnst ! return value integer :: i - + chem_implements_cnst = .false. do i = 1, nspecies @@ -150,13 +153,13 @@ function chem_implements_cnst(name) end function chem_implements_cnst !=============================================================================== - + subroutine chem_init(phys_state, pbuf2d) - !----------------------------------------------------------------------- - ! + !----------------------------------------------------------------------- + ! ! Purpose: initialize parameterized greenhouse gas chemistry ! (declare history variables) - ! + ! !----------------------------------------------------------------------- use physics_buffer, only: physics_buffer_desc use cam_history, only: addfld, add_default, horiz_only @@ -196,7 +199,7 @@ end subroutine chem_init subroutine chem_timestep_init(phys_state, pbuf2d) use physics_buffer, only: physics_buffer_desc - type(physics_state), intent(in):: phys_state(begchunk:endchunk) + type(physics_state), intent(in):: phys_state(begchunk:endchunk) type(physics_buffer_desc), pointer :: pbuf2d(:,:) end subroutine chem_timestep_init @@ -222,7 +225,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o ) real(r8), optional, intent(out) :: fh2o(pcols) ! h2o flux to balance source from chemistry real(r8) :: a(pver),b(pver),c(pver),d(pver) - + real(r8) :: k1(pcols) real(r8) :: k2(pcols) @@ -278,7 +281,7 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o ) l(i,:) = (1._r8 - e(i,:))/det(i,:)/dt elsewhere l(i,:) = 4._r8*k2(i) - endwhere + endwhere cl_f(i,:) = -l(i,:)*(cl(i,:) - det(i,:) + r(i) )*(cl(i,:) + det(i,:) + r(i)) / ( 1._r8 +e(i,:) + dt*l(i,:)*(cl(i,:) + r(i))) cl2_f(i,:) = -cl_f(i,:) / 2._r8 @@ -325,7 +328,7 @@ subroutine chem_init_cnst(name, latvals, lonvals, mask, q) real(r8) :: q_vmr(size(q, 1)) ! volume mixing ratio (ncol) real(r8) :: det(size(q, 1)) real(r8) :: krat(size(q, 1)) - + real(r8) :: k1(size(q, 1)) real(r8) :: k2(size(q, 1)) @@ -347,7 +350,7 @@ subroutine chem_init_cnst(name, latvals, lonvals, mask, q) krat(:) = k1(:) / (4._r8 * k2(:)) h = init_vmr_cl + 2._r8 * init_vmr_cl2 - + det(:) = sqrt(krat(:) * krat(:) + 2._r8 * h * krat(:)) if (trim(name) == trim(species(1)) ) then @@ -412,7 +415,7 @@ subroutine chem_init_restart(File) end subroutine chem_init_restart !================================================================================ subroutine chem_reset_fluxes( fptr, cam_in ) - use camsrfexch, only : cam_in_t + use camsrfexch, only : cam_in_t real(r8), pointer :: fptr(:,:) ! pointer into array data type(cam_in_t), intent(inout) :: cam_in(begchunk:endchunk) @@ -420,7 +423,7 @@ subroutine chem_reset_fluxes( fptr, cam_in ) end subroutine chem_reset_fluxes !================================================================================ subroutine chem_emissions( state, cam_in, pbuf ) - use camsrfexch, only: cam_in_t + use camsrfexch, only: cam_in_t use physics_buffer, only: physics_buffer_desc ! Arguments: diff --git a/src/control/camsrfexch.F90 b/src/control/camsrfexch.F90 index 8111785cd1..1470c46198 100644 --- a/src/control/camsrfexch.F90 +++ b/src/control/camsrfexch.F90 @@ -9,7 +9,7 @@ module camsrfexch use constituents, only: pcnst use ppgrid, only: pcols, begchunk, endchunk use phys_grid, only: get_ncols_p, phys_grid_initialized - use infnan, only: nan, posinf, assignment(=) + use infnan, only: posinf, assignment(=) use cam_abortutils, only: endrun use cam_logfile, only: iulog use srf_field_check, only: active_Sl_ram1, active_Sl_fv, active_Sl_soilw, & @@ -329,11 +329,11 @@ subroutine atm2hub_alloc( cam_out ) allocate (cam_out(c)%nhx_nitrogen_flx(pcols), stat=ierror) if ( ierror /= 0 ) call endrun(sub//': allocation error nhx_nitrogen_flx') - cam_out(c)%nhx_nitrogen_flx(:) = nan + cam_out(c)%nhx_nitrogen_flx(:) = 0._r8 allocate (cam_out(c)%noy_nitrogen_flx(pcols), stat=ierror) if ( ierror /= 0 ) call endrun(sub//': allocation error noy_nitrogen_flx') - cam_out(c)%noy_nitrogen_flx(:) = nan + cam_out(c)%noy_nitrogen_flx(:) = 0._r8 endif From 8c33802404ede88f22e7b7c149f43e63c2362f24 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Sun, 22 Dec 2024 13:39:04 -0700 Subject: [PATCH 55/89] Revert "limit t_sfc to valid temperature range" This reverts commit 6229b1a6c648667e301e02ed31d7c070bf2f97c3. --- src/physics/rrtmgp/rrtmgp_inputs.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/physics/rrtmgp/rrtmgp_inputs.F90 b/src/physics/rrtmgp/rrtmgp_inputs.F90 index 191b6ff8a0..4f73ae9029 100644 --- a/src/physics/rrtmgp/rrtmgp_inputs.F90 +++ b/src/physics/rrtmgp/rrtmgp_inputs.F90 @@ -178,8 +178,6 @@ subroutine rrtmgp_set_state( & tref_max = kdist_sw%get_temp_max() t_rad = merge(t_rad, tref_min, t_rad > tref_min) t_rad = merge(t_rad, tref_max, t_rad < tref_max) - t_sfc = merge(t_sfc, tref_min, t_sfc > tref_min) - t_sfc = merge(t_sfc, tref_max, t_sfc < tref_max) ! Construct arrays containing only daylight columns do i = 1, nday From b851c072ca524133c0210aab10a1ae33905042e5 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Sun, 22 Dec 2024 13:45:08 -0700 Subject: [PATCH 56/89] Update CICE tag to fix bad surface temperature values. --- .gitmodules | 2 +- components/cice | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0176e8431c..0ceaa9a13f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -186,7 +186,7 @@ fxDONOTUSEurl = https://github.com/NCAR/ParallelIO [submodule "cice"] path = components/cice url = https://github.com/ESCOMP/CESM_CICE -fxtag = cesm_cice6_5_0_12 +fxtag = cesm3_cice6_6_0_5 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CESM_CICE diff --git a/components/cice b/components/cice index f14ec8339b..787d3ccf3b 160000 --- a/components/cice +++ b/components/cice @@ -1 +1 @@ -Subproject commit f14ec8339bc5bc4a7a0664da5e247b5cfda531a1 +Subproject commit 787d3ccf3b242214b0add3e474672f0609efcf2d From 726f965bf9610b506fdb15fcc75a72fb3367982e Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Sun, 22 Dec 2024 14:11:06 -0700 Subject: [PATCH 57/89] Initial ChangeLog update. --- doc/ChangeLog | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index cf2aa2517d..50a1d3983b 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,59 @@ =============================================================== +Tag name: cam6_4_0XX +Originator(s): nusbaume +Date: 22 December 2024 +One-line Summary: Revert t_sfc limiter in RRTMGP +Github PR URL: https://github.com/ESCOMP/CAM/pull/XXXX + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + +#1188 - Revert t_sfc limiter + - Also updates the CICE tag to fix the original bad temperatures problem. + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: N/A + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: cacraig, peverwhee + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: + +M .gitmodules +M components/cice + - Update CICE tag to cesm3_cice6_6_0_5 (Github issue #1185) + +M src/physics/rrtmgp/rrtmgp_inputs.F90 + - Revert t_sfc limiter in RRTMGP (Github PR #1184) + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers: + +=============================================================== + Tag name: cam6_4_048 Originator(s): jedwards4b, peverwhee Date: 20 December 2024 From 24e012d6790b73ac78e47821ee970100cbbcd2b3 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 26 Dec 2024 11:03:59 -0700 Subject: [PATCH 58/89] ChangeLog start; code clean up; add ndep diags to reg test modified: cime_config/testdefs/testmods_dirs/cam/outfrq9s_Leung_dust/user_nl_cam modified: doc/ChangeLog modified: src/utils/srf_field_check.F90 --- .../cam/outfrq9s_Leung_dust/user_nl_cam | 2 +- doc/ChangeLog | 131 ++++++++++++++++++ src/utils/srf_field_check.F90 | 4 - 3 files changed, 132 insertions(+), 5 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq9s_Leung_dust/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq9s_Leung_dust/user_nl_cam index 351fe92801..01d1b71f8f 100644 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq9s_Leung_dust/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/outfrq9s_Leung_dust/user_nl_cam @@ -1,6 +1,6 @@ dust_emis_method = 'Leung_2023' -fincl2 = 'dst_a1SF', 'dst_a2SF', 'dst_a3SF' +fincl2 = 'dst_a1SF', 'dst_a2SF', 'dst_a3SF', 'a2x_NHXDEP','a2x_NOYDEP' mfilt=1,1,1,1,1,1 ndens=1,1,1,1,1,1 diff --git a/doc/ChangeLog b/doc/ChangeLog index 746fead140..b535adc98e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,136 @@ =============================================================== +Tag name: cam6_4_??? +Originator(s): fvitt +Date: +One-line Summary: +Github PR URL: + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + + Change logical determinations on how to set nitrogen deposition fluxes which are sent to + surface models through the NUOPC mediator. This sets the nitrogen deposition fluxes to + prescribed CDEP input stream fluxes if corresponding namelist options are set. Otherwise, + the nitrogen deposition fluxes set to chemistry computed fluxes if the chemistry is capable + of providing the fluxes. (Github issue #1196) + +Describe any changes made to build system: + +Describe any changes made to the namelist: + +List any changes to the defaults for the boundary datasets: + +Describe any substantial timing or memory changes: + +Code reviewed by: + +List all files eliminated: + +List all files added and what they do: + +List all existing files that have been modified, and describe the changes: + +M bld/build-namelist + - change how default ndep_stream namelist options are set + . check if chemistry is capable of producing nitrogen deposition fluxes + . set defaults only if not simple physics nor aqua-planet configuration + +M bld/namelist_files/namelist_defaults_cam.xml + - default ndep_stream namelist settings for perpetual year 2000 configuration + +M bld/namelist_files/namelist_definition.xml + - updates to stream_ndep_* namelist descriptions + +M bld/namelist_files/use_cases/1850_cam_lt.xml +M bld/namelist_files/use_cases/1850_cam_mt.xml +M bld/namelist_files/use_cases/2010_cam6.xml +M bld/namelist_files/use_cases/hist_cam_lt.xml +M bld/namelist_files/use_cases/hist_cam_mt.xml +M bld/namelist_files/use_cases/sd_cam6.xml +M bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml + - stream_ndep_* namelist settings for use cases + +M cime_config/buildnml + - remove the use of CAM_STREAM_NDEP* xml vars to set stream_ndep* namelist options + +M cime_config/config_component.xml + - remove CAM_STREAM_NDEP* xml vars + +M src/chemistry/geoschem/chemistry.F90 +M src/chemistry/pp_none/chemistry.F90 +M src/chemistry/pp_terminator/chemistry.F90 + - add chem_has_ndep_flx flag -- set to .FALSE. for these chem pckgs + +M src/chemistry/mozart/chemistry.F90 + - add chem_has_ndep_flx flag + - add check for prescribed nitrogen depostion fluxes + +M src/chemistry/mozart/mo_chm_diags.F90 + - check for NOy and NHx species in chemistry to determine if + chemistry can produce nitrogen deposition fluxes + +M src/control/camsrfexch.F90 + - allocate cam_out nitro dep flx arrays only if not simple phys and not aqua-planet + +M src/control/runtime_opts.F90 + - invoke stream_ndep_readnl sooner in the initialization phase -- from read_namelist + +M src/cpl/nuopc/atm_import_export.F90 + - set out going ndep fluxes only if not simple physics and not aqua-planet + - set out going ndep fluxes to prescribed ndep stream fields, otherwise, + set chemistry computed fluxes if available. + +M src/cpl/nuopc/atm_stream_ndep.F90 + - add readnl routine -- seperated from init routine which can be invoked from + runtime_opts -- earlier in initialization + - set default use_ndep_stream flag to .false. + +M src/physics/cam/cam_diagnostics.F90 + - add 'a2x_NOYDEP' and 'a2x_NHXDEP' history fields + +M src/utils/srf_field_check.F90 + - removed active_Faxa_nhx and active_Faxa_noy routine flags which were not useful + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers, i.e., +- what code configurations: +- what platforms/compilers: +- nature of change (roundoff; larger than roundoff but same climate; new + climate): + +If bitwise differences were observed, how did you show they were no worse +than roundoff? + +If this tag changes climate describe the run(s) done to evaluate the new +climate in enough detail that it(they) could be reproduced, i.e., +- source tag (all code used must be in the repository): +- platform/compilers: +- configure commandline: +- build-namelist command (or complete namelist): +- MSS location of output: + +MSS location of control simulations used to validate new climate: + +URL for AMWG diagnostics output used to validate new climate: + +=============================================================== +=============================================================== + Tag name: cam6_4_047 Originator(s): jedwards4b, fvitt Date: 19 November 2024 diff --git a/src/utils/srf_field_check.F90 b/src/utils/srf_field_check.F90 index a0aa0cb0f5..97d210bb5e 100644 --- a/src/utils/srf_field_check.F90 +++ b/src/utils/srf_field_check.F90 @@ -17,10 +17,6 @@ module srf_field_check logical, public, protected :: active_Fall_fco2_lnd = .false. logical, public, protected :: active_Faoo_fco2_ocn = .false. - ! output from atm - logical, public, protected :: active_Faxa_nhx = .false. - logical, public, protected :: active_Faxa_noy = .false. - public :: set_active_Sl_ram1 public :: set_active_Sl_fv public :: set_active_Sl_soilw From 82a3c9c6ac8827352dc2b3eea558ea8bb9972e07 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 26 Dec 2024 12:41:35 -0700 Subject: [PATCH 59/89] fix restart problem with nitrogen flux history fields modified: src/physics/cam/cam_diagnostics.F90 modified: src/physics/cam/physpkg.F90 --- src/physics/cam/cam_diagnostics.F90 | 7 ------- src/physics/cam/physpkg.F90 | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 3a01d9536e..d351ec05f8 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -1906,13 +1906,6 @@ subroutine diag_export(cam_out) call outfld('a2x_DSTDRY4', cam_out%dstdry4, pcols, lchnk) end if - if (associated(cam_out%nhx_nitrogen_flx)) then - call outfld('a2x_NHXDEP', cam_out%nhx_nitrogen_flx, pcols, lchnk) - end if - if (associated(cam_out%noy_nitrogen_flx)) then - call outfld('a2x_NOYDEP', cam_out%noy_nitrogen_flx, pcols, lchnk) - end if - end subroutine diag_export !####################################################################### diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index ba36670ce8..a9ffeb91e5 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1988,6 +1988,14 @@ subroutine tphysac (ztodt, cam_in, & call clybry_fam_set( ncol, lchnk, map2chm, state%q, pbuf ) + ! output these here -- after updates by chem_timestep_tend or export_fields within the current time step + if (associated(cam_out%nhx_nitrogen_flx)) then + call outfld('a2x_NHXDEP', cam_out%nhx_nitrogen_flx, pcols, lchnk) + end if + if (associated(cam_out%noy_nitrogen_flx)) then + call outfld('a2x_NOYDEP', cam_out%noy_nitrogen_flx, pcols, lchnk) + end if + end subroutine tphysac subroutine tphysbc (ztodt, state, & From bba4e59ceeb7d17fe6bac0738e066811aa20996c Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 26 Dec 2024 15:08:14 -0700 Subject: [PATCH 60/89] add addfld calls to cam7 phys modified: src/physics/cam7/physpkg.F90 --- src/physics/cam7/physpkg.F90 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 83d03c46d1..d0e00b4673 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -2470,6 +2470,14 @@ subroutine tphysac (ztodt, cam_in, & call clybry_fam_set( ncol, lchnk, map2chm, state%q, pbuf ) + ! output these here -- after updates by chem_timestep_tend or export_fields within the current time step + if (associated(cam_out%nhx_nitrogen_flx)) then + call outfld('a2x_NHXDEP', cam_out%nhx_nitrogen_flx, pcols, lchnk) + end if + if (associated(cam_out%noy_nitrogen_flx)) then + call outfld('a2x_NOYDEP', cam_out%noy_nitrogen_flx, pcols, lchnk) + end if + end subroutine tphysac subroutine tphysbc (ztodt, state, & From 9066aee7bdef48926fb02b81bed604329c2ff8cf Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 26 Dec 2024 16:23:47 -0700 Subject: [PATCH 61/89] units correction in diagnostics modified: src/cpl/nuopc/atm_import_export.F90 modified: src/cpl/nuopc/atm_stream_ndep.F90 modified: src/physics/cam/cam_diagnostics.F90 --- src/cpl/nuopc/atm_import_export.F90 | 15 +++------------ src/cpl/nuopc/atm_stream_ndep.F90 | 9 +++++++-- src/physics/cam/cam_diagnostics.F90 | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index b5b56b8112..fa2a91d943 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -923,7 +923,6 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) integer :: ncols ! Number of columns integer :: nstep logical :: exists - real(r8) :: scale_ndep ! 2d pointers real(r8), pointer :: fldptr_ndep(:,:) real(r8), pointer :: fldptr_bcph(:,:) , fldptr_ocph(:,:) @@ -1121,6 +1120,7 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) end if if (ndep_stream_active.or.chem_has_ndep_flx) then + ! Nitrogen dep fluxes are obtained from the ndep input stream if input data is available ! otherwise computed by chemistry if (ndep_stream_active) then @@ -1128,23 +1128,14 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) ! get ndep fluxes from the stream call stream_ndep_interp(cam_out, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - ! NDEP read from forcing is expected to be in units of gN/m2/sec - but the mediator - ! expects units of kgN/m2/sec - scale_ndep = .001_r8 - - else if (chem_has_ndep_flx) then - - ! Assume chemistry computes ndep fluxes, then its in units of kgN/m2/s - and the mediator expects - ! units of kgN/m2/sec, so the following conversion needs to happen - scale_ndep = 1._r8 end if g = 1 do c = begchunk,endchunk do i = 1,get_ncols_p(c) - fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) - fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * scale_ndep * mod2med_areacor(g) + fldptr_ndep(1,g) = cam_out(c)%nhx_nitrogen_flx(i) * mod2med_areacor(g) + fldptr_ndep(2,g) = cam_out(c)%noy_nitrogen_flx(i) * mod2med_areacor(g) g = g + 1 end do end do diff --git a/src/cpl/nuopc/atm_stream_ndep.F90 b/src/cpl/nuopc/atm_stream_ndep.F90 index eed6ac619e..f54509b269 100644 --- a/src/cpl/nuopc/atm_stream_ndep.F90 +++ b/src/cpl/nuopc/atm_stream_ndep.F90 @@ -246,6 +246,11 @@ subroutine stream_ndep_interp(cam_out, rc) integer :: mcdate ! Current model date (yyyymmdd) real(r8), pointer :: dataptr1d_nhx(:) real(r8), pointer :: dataptr1d_noy(:) + + ! NDEP read from forcing is expected to be in units of gN/m2/sec - but the mediator + ! expects units of kgN/m2/sec + real(r8), parameter :: scale_ndep = .001_r8 + !----------------------------------------------------------------------- ! Advance sdat stream @@ -269,8 +274,8 @@ subroutine stream_ndep_interp(cam_out, rc) g = 1 do c = begchunk,endchunk do i = 1,get_ncols_p(c) - cam_out(c)%nhx_nitrogen_flx(i) = dataptr1d_nhx(g) - cam_out(c)%noy_nitrogen_flx(i) = dataptr1d_noy(g) + cam_out(c)%nhx_nitrogen_flx(i) = dataptr1d_nhx(g) * scale_ndep + cam_out(c)%noy_nitrogen_flx(i) = dataptr1d_noy(g) * scale_ndep g = g + 1 end do end do diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index d351ec05f8..6006a6e8c8 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -568,8 +568,8 @@ subroutine diag_init_moist(pbuf2d) call addfld('a2x_DSTWET4', horiz_only, 'A', 'kg/m2/s', 'wetdep of dust (bin4)') call addfld('a2x_DSTDRY4', horiz_only, 'A', 'kg/m2/s', 'drydep of dust (bin4)') - call addfld('a2x_NOYDEP', horiz_only, 'A', 'kg/m2/s', 'NOy Deposition Flux') - call addfld('a2x_NHXDEP', horiz_only, 'A', 'kg/m2/s', 'NHx Deposition Flux') + call addfld('a2x_NOYDEP', horiz_only, 'A', 'kgN/m2/s', 'NOy Deposition Flux') + call addfld('a2x_NHXDEP', horiz_only, 'A', 'kgN/m2/s', 'NHx Deposition Flux') ! defaults if (history_amwg) then From 97fd80156c96244d769593f3ad8b8a8bbb614e82 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Sat, 28 Dec 2024 11:26:00 -0700 Subject: [PATCH 62/89] set fldptr_ndep to zero for no flux cases modified: src/cpl/nuopc/atm_import_export.F90 --- src/cpl/nuopc/atm_import_export.F90 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cpl/nuopc/atm_import_export.F90 b/src/cpl/nuopc/atm_import_export.F90 index fa2a91d943..c5ad5c253d 100644 --- a/src/cpl/nuopc/atm_import_export.F90 +++ b/src/cpl/nuopc/atm_import_export.F90 @@ -1109,6 +1109,8 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) call state_getfldptr(exportState, 'Faxa_ndep', fldptr2d=fldptr_ndep, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + fldptr_ndep(:,:) = 0._r8 + if (.not. (simple_phys .or. aqua_planet)) then ! The ndep_stream_nl namelist group is read in stream_ndep_init. This sets whether @@ -1140,10 +1142,6 @@ subroutine export_fields( gcomp, model_mesh, model_clock, cam_out, rc) end do end do - else - - fldptr_ndep(:,:) = 0._r8 - end if end if From 31796b2677e6389862948a832f075011f3ca08d2 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Sat, 28 Dec 2024 14:18:58 -0700 Subject: [PATCH 63/89] namelist fixes modified: bld/namelist_files/namelist_defaults_cam.xml modified: bld/namelist_files/use_cases/1850_cam6.xml modified: bld/namelist_files/use_cases/hist_cam6.xml --- bld/namelist_files/namelist_defaults_cam.xml | 3 --- bld/namelist_files/use_cases/1850_cam6.xml | 5 +++++ bld/namelist_files/use_cases/hist_cam6.xml | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 501047a1bc..ab2707290c 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2063,9 +2063,6 @@ lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -1850 -2015 -1850 2000 2000 1 diff --git a/bld/namelist_files/use_cases/1850_cam6.xml b/bld/namelist_files/use_cases/1850_cam6.xml index 7f4cf09a5c..14d0c61526 100644 --- a/bld/namelist_files/use_cases/1850_cam6.xml +++ b/bld/namelist_files/use_cases/1850_cam6.xml @@ -52,6 +52,11 @@ atm/cam/chem/emis/elev/H2O_emission_CH4_oxidationx2_elev_3DmonthlyL70_1850climoCMIP6piControl001_y21-50avg_c180802.nc +lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc +1850 +1850 +1 + 1850 diff --git a/bld/namelist_files/use_cases/hist_cam6.xml b/bld/namelist_files/use_cases/hist_cam6.xml index ac93a56a62..fff3618c07 100644 --- a/bld/namelist_files/use_cases/hist_cam6.xml +++ b/bld/namelist_files/use_cases/hist_cam6.xml @@ -30,6 +30,10 @@ 'SERIAL' 'CO2','CH4','N2O','CFC11eq','CFC12' + 1850 + 2015 + 1850 + 1850-2000 From bdb3b768da79bebb4154a8e1a4597883de700261 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 30 Dec 2024 23:54:15 -0500 Subject: [PATCH 64/89] Update to head of atmos_phys with check_energy_fix_run arguments --- .gitmodules | 2 +- src/atmos_phys | 2 +- src/physics/cam/check_energy.F90 | 21 +++++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.gitmodules b/.gitmodules index 91690771e1..d07d5f8ac5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/ESCOMP/atmospheric_physics - fxtag = atmos_phys0_07_000 + fxtag = 8e3d0bdff98ff70a4e815160ebd13a150c662a12 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index e10f81151e..8e3d0bdff9 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit e10f81151ecef5416462472ef0e52810dc82e412 +Subproject commit 8e3d0bdff98ff70a4e815160ebd13a150c662a12 diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 7af3a32bda..d1d59e173f 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -877,6 +877,9 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) real(r8) :: heat_out(pcols) character(len=64) :: dummy_scheme_name ! dummy scheme name for CCPP-ized scheme + integer :: errflg + character(len=512) :: errmsg + lchnk = state%lchnk ncol = state%ncol @@ -904,14 +907,16 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) ! Call the CCPP-ized subroutine (for non-SCAM) ! to compute the effective sensible heat flux and save to ptend%s call check_energy_fix_run( & - ncol = ncol, & - pver = pver, & - pint = state%pint(:ncol,:), & - gravit = gravit, & - heat_glob = heat_glob, & - ptend_s = ptend%s(:ncol,:), & - eshflx = eshflx(:ncol), & - scheme_name = dummy_scheme_name & + ncol = ncol, & + pver = pver, & + pint = state%pint(:ncol,:), & + gravit = gravit, & + heat_glob = heat_glob, & + ptend_s = ptend%s(:ncol,:), & + eshflx = eshflx(:ncol), & + scheme_name = dummy_scheme_name, & + errmsg = errmsg, & + errflg = errflg & ) end subroutine check_energy_cam_fix From 0881a22bde02cf059f3d383f0de13cf35a492108 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 31 Dec 2024 09:57:33 -0500 Subject: [PATCH 65/89] Update to atmos_phys0_07_001 --- .gitmodules | 2 +- src/atmos_phys | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 29c2e7bdac..1809a94e55 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/ESCOMP/atmospheric_physics - fxtag = 8e3d0bdff98ff70a4e815160ebd13a150c662a12 + fxtag = atmos_phys0_07_001 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index 8e3d0bdff9..c3de8468f7 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 8e3d0bdff98ff70a4e815160ebd13a150c662a12 +Subproject commit c3de8468f7b245a939448f4ca6d3ef386584e92d From b7b4c3cfad202facbb6064e33f607c26f1988f03 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 31 Dec 2024 14:02:57 -0500 Subject: [PATCH 66/89] Finalize ChangeLog for cam6_4_050. --- doc/ChangeLog | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index dcc4560393..8ae657fda9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== -Tag name: +Tag name: cam6_4_050 Originator(s): jimmielin -Date: 30 Dec 2024 +Date: 31 Dec 2024 One-line Summary: Implement CCPPized check_energy_chng and check_energy_fix Github PR URL: https://github.com/ESCOMP/CAM/pull/1180 @@ -37,7 +37,7 @@ M src/atmos_phys Save cp_or_cv_dycore in state snapshot M src/control/cam_snapshot_common.F90 -New CAM interfaces to CCPPized routines, when avaialble +New CAM interfaces to CCPPized routines, when available M src/physics/cam/check_energy.F90 Update calls to CCPPized routines, when available @@ -55,11 +55,22 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: -derecho/nvhpc/aux_cam: +SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) +SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) +SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: PASS) + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + +derecho/nvhpc/aux_cam: All PASS izumi/nag/aux_cam: -izumi/gnu/aux_cam: +DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: All PASS Summarize any changes to answers: B4B From 88bf77850d4dafccf037a0bba46477873baeb4b7 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Tue, 31 Dec 2024 13:23:48 -0700 Subject: [PATCH 67/89] Add comments describing new vertical level variables. --- src/physics/cam/clubb_intr.F90 | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 6374a3dc2d..a9878bc474 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -31,7 +31,7 @@ module clubb_intr #ifdef CLUBB_SGS use clubb_api_module, only: pdf_parameter, implicit_coefs_terms - use clubb_api_module, only: clubb_config_flags_type, grid, stats, & + use clubb_api_module, only: clubb_config_flags_type, grid, stats, & nu_vertical_res_dep, stats_metadata_type, & hm_metadata_type, sclr_idx_type @@ -52,7 +52,7 @@ module clubb_intr stats_sfc(pcols) ! stats_sfc type (hm_metadata_type) :: & hm_metadata - + type (stats_metadata_type) :: & stats_metadata @@ -60,8 +60,8 @@ module clubb_intr sclr_idx integer :: & - nzm_clubb, & - nzt_clubb + nzm_clubb, & !Number of vertical levels used by CLUBB momentum variables + nzt_clubb !Number of vertical levels used by CLUBB thermodynamic variables #endif private @@ -99,7 +99,7 @@ module clubb_intr ! These are zero by default, but will be set by SILHS before they are used by subcolumns integer :: & - hydromet_dim = 0, & + hydromet_dim = 0, & pdf_dim = 0 @@ -121,7 +121,7 @@ module clubb_intr hm_metadata #endif #endif - + ! ------------ ! ! Private data ! ! ------------ ! @@ -344,7 +344,7 @@ module clubb_intr clubb_l_mono_flux_lim_um, & ! Flag to turn on monotonic flux limiter for um clubb_l_mono_flux_lim_vm, & ! Flag to turn on monotonic flux limiter for vm clubb_l_mono_flux_lim_spikefix, & ! Flag to implement monotonic flux limiter code that - ! eliminates spurious drying tendencies at model top + ! eliminates spurious drying tendencies at model top clubb_l_host_applies_sfc_fluxes ! Whether the host model applies the surface fluxes logical :: & @@ -353,7 +353,7 @@ module clubb_intr ! Constant parameters logical, parameter, private :: & l_implemented = .true. ! Implemented in a host model (always true) - + logical, parameter, private :: & apply_to_heat = .false. ! Apply WACCM energy fixer to heat or not (.true. = yes (duh)) @@ -1740,7 +1740,7 @@ subroutine clubb_ini_cam(pbuf2d) clubb_params_single_col(iwpxp_Ri_exp) = clubb_wpxp_Ri_exp clubb_params_single_col(iz_displace) = clubb_z_displace - ! Override clubb default + ! Override clubb default if ( trim(subcol_scheme) == 'SILHS' ) then clubb_config_flags%saturation_formula = saturation_flatau else @@ -1749,7 +1749,7 @@ subroutine clubb_ini_cam(pbuf2d) ! Define model constant parameters call setup_parameters_model_api( theta0, ts_nudge, clubb_params_single_col(iSkw_max_mag) ) - + ! Set up CLUBB core. Note that some of these inputs are overwritten ! when clubb_tend_cam is called. The reason is that heights can change ! at each time step, which is why dummy arrays are read in here for heights @@ -1892,7 +1892,7 @@ subroutine clubb_ini_cam(pbuf2d) dum3 = 300._r8 if (stats_metadata%l_stats) then - + call stats_init_clubb( .true., dum1, dum2, & nzm_clubb, nzm_clubb, nzm_clubb, dum3, & stats_zt(:), stats_zm(:), stats_sfc(:), & @@ -2591,7 +2591,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & dpdlfice, & dpdlft, & detnliquid - + real(r8), dimension(pcols,pverp) :: & wprcp_clubb, & wpthvp_clubb @@ -2614,7 +2614,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclr, & edsclr, & n - + #endif call t_startf('clubb_tend_cam') @@ -2763,7 +2763,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_liqsupersat) then call pbuf_get_field(pbuf, npccn_idx, npccn) endif - + ! Define the grid box size. CLUBB needs this information to determine what ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids @@ -2865,7 +2865,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, state1%s, state1%pint, & !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, state1%phis, & !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & - !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & + !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & !$acc cloud_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & @@ -2889,7 +2889,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, clubb_params, sfc_elevation, wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc radf, wpthlp_sfc, clubb_params, sfc_elevation, wprtp_sfc, upwp_sfc, vpwp_sfc, & !$acc rtm_ref, thlm_ref, um_ref, vm_ref, ug, vg, p_in_Pa, exner, um_pert_inout, & !$acc inv_exner_clubb_surf, thlprcp_out, zi_g, zt_g, qrl_clubb, & !$acc pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, pdf_zm_mixt_frac, & @@ -3001,7 +3001,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_pert_inout(i,k) = 0.0_r8 upwp_pert_inout(i,k) = 0.0_r8 vpwp_pert_inout(i,k) = 0.0_r8 - + ! Initialize these to prevent crashing behavior wprcp_out(i,k) = 0._r8 rcm_in_layer_out(i,k) = 0._r8 @@ -3040,7 +3040,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do end do - + !$acc parallel loop gang vector collapse(2) default(present) do sclr = 1, sclr_dim do i=1, ncol @@ -3126,7 +3126,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & s_awv_output(i,k) = 0._r8 mf_thlflx_output(i,k) = 0._r8 mf_qtflx_output(i,k) = 0._r8 - end do + end do end do end if @@ -3254,7 +3254,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state inv_exner_clubb(i,k) = 1._r8 / ( ( state1%pmid(i,k) / p0_clubb )**( rairv(i,k,lchnk) / cpairv(i,k,lchnk) ) ) - + ! Compute virtual potential temperature, which is needed for CLUBB thv(i,k) = state1%t(i,k) * inv_exner_clubb(i,k) & * ( 1._r8 + zvir * state1%q(i,k,ixq) - state1%q(i,k,ixcldliq) ) @@ -3272,7 +3272,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo enddo - + !$acc parallel loop gang vector default(present) do i = 1, ncol rtm(i,pverp) = rtm(i,pver) @@ -3409,7 +3409,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:ACCR') call t_startf('clubb_tend_cam:NAR') !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) - + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) @@ -3512,14 +3512,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol - + um_in(i,k) = um(i,pverp-k+1) vm_in(i,k) = vm(i,pverp-k+1) upwp_in(i,k) = upwp(i,pverp-k+1) @@ -3866,7 +3866,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:do_cldcool') end if - + ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (stats_metadata%l_stats) then @@ -4035,7 +4035,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do call t_stopf('clubb_tend_cam:flip-index') - + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pverp do i=1, ncol @@ -4190,7 +4190,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pverp do i=1, ncol @@ -4327,7 +4327,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if end do - + rvmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) rcmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) rimtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) @@ -5147,7 +5147,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Set stats_variables variables with inputs from calling subroutine stats_metadata%l_stats = l_stats_in - + stats_metadata%stats_tsamp = stats_tsamp_in stats_metadata%stats_tout = stats_tout_in From 454ce0a4c90b3be3899f03041015defb37d5c33c Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Wed, 1 Jan 2025 12:12:01 -0500 Subject: [PATCH 68/89] mods and tests for QPMT configuration --- .../use_cases/aquaplanet_cam7.xml | 2 ++ cime_config/testdefs/testlist_cam.xml | 18 ++++++++++++++++++ doc/ChangeLog | 14 +++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/bld/namelist_files/use_cases/aquaplanet_cam7.xml b/bld/namelist_files/use_cases/aquaplanet_cam7.xml index efbfff14b1..8e1c9fba5a 100644 --- a/bld/namelist_files/use_cases/aquaplanet_cam7.xml +++ b/bld/namelist_files/use_cases/aquaplanet_cam7.xml @@ -5,6 +5,8 @@ atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc +atm/cam/inic/se/QPMT_L93_ne3pg3_c241223.nc +atm/cam/inic/se/QPMT_L93_ne30pg3_c241223.nc 0. diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index f4b76a14a0..c26abe5512 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -208,6 +208,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/doc/ChangeLog b/doc/ChangeLog index 0766808971..5452b8a48c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -4,7 +4,7 @@ Tag name: Originator(s): eaton Date: One-line Summary: Add QPLT and QPMT compsets, plus misc. -Github PR URL: +Github PR URL: https://github.com/ESCOMP/CAM/pull/1203 Purpose of changes (include the issue number and title text for each relevant GitHub issue): @@ -36,6 +36,15 @@ Describe any changes made to the namelist: none List any changes to the defaults for the boundary datasets: . add spun up initial files for QPLT compset on ne3pg3 and ne30pg3 grids. + atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc + atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc + +. add spun up initial files for QPMT compset on ne3pg3 and ne30pg3 grids. + atm/cam/inic/se/QPMT_L93_ne3pg3_c241223.nc + atm/cam/inic/se/QPMT_L93_ne30pg3_c241223.nc + +. add ozone dataset for high top aquaplanet runs + atm/cam/ozone/aquaplanet_ozone_hightop_c20180412.nc Describe any substantial timing or memory changes: n/a @@ -69,6 +78,7 @@ bld/namelist_files/use_cases/aquaplanet_cam7.xml - Add spun-up IC files. This allows us to remove the ic_ymd attribute which should not be needed for aquaplanet runs. Removing ic_ymd enables testing with arbitrary start dates. + - Add ozone dataset for high top aquaplanet configuration cime_config/config_component.xml . CAM_CONFIG_OPTS @@ -88,8 +98,10 @@ cime_config/testdefs/testlist_cam.xml . remove non-working DAE test . replace ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s by ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp +. Add ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq3s . replace ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp by ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s +. Add ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPMT.izumi_gnu.cam-outfrq9s cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands . remove "./xmlchange CAM_NML_USE_CASE=UNSET" From 38a3091c56ab2ff4eacaf26376a2f2a06053f057 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Wed, 1 Jan 2025 12:20:35 -0500 Subject: [PATCH 69/89] update ChangeLog --- doc/ChangeLog | 332 +++++++++++++++++++++++++------------------------- 1 file changed, 166 insertions(+), 166 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index f496cfcdb6..6ae50ee3d8 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,170 @@ =============================================================== + +Tag name: +Originator(s): eaton +Date: +One-line Summary: Add QPLT and QPMT compsets, plus misc. +Github PR URL: https://github.com/ESCOMP/CAM/pull/1203 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + +Issue #814 - Introduce QPC7 and possibly QPS7 aquaplanet compsets + - Analogous to FLT and FMT compset names, create QPLT and QPMT compsets. + - Open new issue to address QPS7. + - The new aquaplanet configurations use '-chem none' to eliminate the + aerosols. This is much faster and requires much less memory than a + configuration that leaves the default chemistry in place and removes + aerosols by zeroing the initial concentrations and emission sources. + +Issue #1159 - Prealpha tests exceeding wallclock + - increased time limit to 20 minutes for these prealpha tests: + ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s + ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s + +Issue #670 - DAE test broken + - ChangeLog indicates that this test has never worked since it was added + in cam6_2_046 (2020-09-01). Test removed. + +Issue #807 - add UT and UQ to cam_diagnostics + - Add UT and UQ. Note that other possible fields mentioned in the issue, + i.e., OMEGA2, OMEGAQ, OMEGAU, and OMEGAV, are already implemented. + OMEGA2 is called OMGAOMGA. + +Describe any changes made to build system: none + +Describe any changes made to the namelist: none + +List any changes to the defaults for the boundary datasets: +. add spun up initial files for QPLT compset on ne3pg3 and ne30pg3 grids. + atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc + atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc + +. add spun up initial files for QPMT compset on ne3pg3 and ne30pg3 grids. + atm/cam/inic/se/QPMT_L93_ne3pg3_c241223.nc + atm/cam/inic/se/QPMT_L93_ne30pg3_c241223.nc + +. add ozone dataset for high top aquaplanet runs + atm/cam/ozone/aquaplanet_ozone_hightop_c20180412.nc + +Describe any substantial timing or memory changes: n/a + +Code reviewed by: + +List all files eliminated: + +cime_config/testdefs/testmods_dirs/cam/dae/shell_commands +cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam +cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl +test/system/da_cam_no_data_mod.sh +. DAE test removed + +List all files added and what they do: none + +List all existing files that have been modified, and describe the changes: + +bld/namelist_files/namelist_defaults_cam.xml +. replace current entry for ne3np4 L58 aquaplanet with + QPLT_L58_ne3pg3_c241127.nc. +. add new file for ne30np4 L58 aquaplanet. + +bld/namelist_files/use_cases/aquaplanet_cam7.xml +. use case file for QPLT and QPMT. Same as for QPC6 except: + - set f11vmr=f12vmr=0 to override the non-zero default values from + namelist_defaults_cam.xml. + - set prescribed_aero_file="" and prescribed_aero_specifier="" to + override the default bulk aerosol settings from build-namelist. + - set rad_climate to just make the GHGs radiatively active to override + the default build-namelist setting which includes bulk aerosols. + - Add spun-up IC files. This allows us to remove the ic_ymd attribute + which should not be needed for aquaplanet runs. Removing ic_ymd + enables testing with arbitrary start dates. + - Add ozone dataset for high top aquaplanet configuration + +cime_config/config_component.xml +. CAM_CONFIG_OPTS + - add match for _CAM70.*_SLND_SICE_DOCN%AQP to set '-chem none' +. CAM_NML_USE_CASE + - add match for 2000_CAM70.*_SLND_SICE_DOCN%AQP to use aquaplanet_cam7. + This match will work for both %LT and %MT configs. + +cime_config/config_compsets.xml +. add QPLT = 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV +. add QPMT = 2000_CAM70%MT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV + +cime_config/testdefs/testlist_cam.xml +. increase time limit to 20 minutes for these prealpha tests: + ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s + ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s +. remove non-working DAE test +. replace ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s + by ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp +. Add ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq3s +. replace ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp + by ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s +. Add ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPMT.izumi_gnu.cam-outfrq9s + +cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands +. remove "./xmlchange CAM_NML_USE_CASE=UNSET" + +cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam +. add CS_SNOWCERT and CS_SNOWPOSS to fexcl1 + +src/chemistry/mozart/mo_drydep.F90 +. get_landuse_and_soilw_from_file + - restrict the INFO messages to only print from masterproc + +src/physics/cam/cam_diagnostics.F90 +. diag_init_dry + - add addfld call for UT, and corresponding add_default for UT inside the + history_eddy conditional. +. diag_phys_writeout_dry + - add calculation and outfld call for UT +. diag_init_moist + - add addfld call for UQ, and corresponding add_default for UQ inside the + history_eddy conditional. +. diag_phys_writeout_moist + - add calculation and outfld call for UQ + +src/physics/cam/microp_aero.F90 +. microp_aero_run + - add condition that number of bulk aerosols must be > 0 before calling + ndrop_bam_run. + +src/physics/cam/nucleate_ice_cam.F90 +. nucleate_ice_cam_calc + - add conditionals so naer2 array not referenced when there are no + aerosols. + +src/physics/cam/vertical_diffusion.F90 +. vertical_diffusion_init + - fix conditional around add_default call for UFLX and VFLX so those + fields aren't added if they're not computed. + +src/physics/cam7/physpkg.F90 +. tphysbc + - add conditionals so modal aerosol calculations only called when modal + aerosols are present. + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers: + +=============================================================== +=============================================================== Tag name: cam6_4_050 Originator(s): jimmielin Date: 31 Dec 2024 @@ -521,172 +687,6 @@ this tag and confirmed that there were no DIFFs =============================================================== -Tag name: -Originator(s): eaton -Date: -One-line Summary: Add QPLT and QPMT compsets, plus misc. -Github PR URL: https://github.com/ESCOMP/CAM/pull/1203 - -Purpose of changes (include the issue number and title text for each relevant GitHub issue): - -Issue #814 - Introduce QPC7 and possibly QPS7 aquaplanet compsets - - Analogous to FLT and FMT compset names, create QPLT and QPMT compsets. - - Open new issue to address QPS7. - - The new aquaplanet configurations use '-chem none' to eliminate the - aerosols. This is much faster and requires much less memory than a - configuration that leaves the default chemistry in place and removes - aerosols by zeroing the initial concentrations and emission sources. - -Issue #1159 - Prealpha tests exceeding wallclock - - increased time limit to 20 minutes for these prealpha tests: - ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s - ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s - -Issue #670 - DAE test broken - - ChangeLog indicates that this test has never worked since it was added - in cam6_2_046 (2020-09-01). Test removed. - -Issue #807 - add UT and UQ to cam_diagnostics - - Add UT and UQ. Note that other possible fields mentioned in the issue, - i.e., OMEGA2, OMEGAQ, OMEGAU, and OMEGAV, are already implemented. - OMEGA2 is called OMGAOMGA. - -Describe any changes made to build system: none - -Describe any changes made to the namelist: none - -List any changes to the defaults for the boundary datasets: -. add spun up initial files for QPLT compset on ne3pg3 and ne30pg3 grids. - atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc - atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc - -. add spun up initial files for QPMT compset on ne3pg3 and ne30pg3 grids. - atm/cam/inic/se/QPMT_L93_ne3pg3_c241223.nc - atm/cam/inic/se/QPMT_L93_ne30pg3_c241223.nc - -. add ozone dataset for high top aquaplanet runs - atm/cam/ozone/aquaplanet_ozone_hightop_c20180412.nc - -Describe any substantial timing or memory changes: n/a - -Code reviewed by: - -List all files eliminated: - -cime_config/testdefs/testmods_dirs/cam/dae/shell_commands -cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cam -cime_config/testdefs/testmods_dirs/cam/dae/user_nl_cpl -test/system/da_cam_no_data_mod.sh -. DAE test removed - -List all files added and what they do: none - -List all existing files that have been modified, and describe the changes: - -bld/namelist_files/namelist_defaults_cam.xml -. replace current entry for ne3np4 L58 aquaplanet with - QPLT_L58_ne3pg3_c241127.nc. -. add new file for ne30np4 L58 aquaplanet. - -bld/namelist_files/use_cases/aquaplanet_cam7.xml -. use case file for QPLT and QPMT. Same as for QPC6 except: - - set f11vmr=f12vmr=0 to override the non-zero default values from - namelist_defaults_cam.xml. - - set prescribed_aero_file="" and prescribed_aero_specifier="" to - override the default bulk aerosol settings from build-namelist. - - set rad_climate to just make the GHGs radiatively active to override - the default build-namelist setting which includes bulk aerosols. - - Add spun-up IC files. This allows us to remove the ic_ymd attribute - which should not be needed for aquaplanet runs. Removing ic_ymd - enables testing with arbitrary start dates. - - Add ozone dataset for high top aquaplanet configuration - -cime_config/config_component.xml -. CAM_CONFIG_OPTS - - add match for _CAM70.*_SLND_SICE_DOCN%AQP to set '-chem none' -. CAM_NML_USE_CASE - - add match for 2000_CAM70.*_SLND_SICE_DOCN%AQP to use aquaplanet_cam7. - This match will work for both %LT and %MT configs. - -cime_config/config_compsets.xml -. add QPLT = 2000_CAM70%LT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV -. add QPMT = 2000_CAM70%MT_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV - -cime_config/testdefs/testlist_cam.xml -. increase time limit to 20 minutes for these prealpha tests: - ERP_Ln9.f09_f09_mg17.FHIST_BGC.derecho_intel.cam-outfrq9s - ERP_Ln9.f09_f09_mg17.FHIST.derecho_intel.cam-outfrq9s -. remove non-working DAE test -. replace ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s - by ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp -. Add ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq3s -. replace ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp - by ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s -. Add ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPMT.izumi_gnu.cam-outfrq9s - -cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/shell_commands -. remove "./xmlchange CAM_NML_USE_CASE=UNSET" - -cime_config/testdefs/testmods_dirs/cam/outfrq3s_cosp/user_nl_cam -. add CS_SNOWCERT and CS_SNOWPOSS to fexcl1 - -src/chemistry/mozart/mo_drydep.F90 -. get_landuse_and_soilw_from_file - - restrict the INFO messages to only print from masterproc - -src/physics/cam/cam_diagnostics.F90 -. diag_init_dry - - add addfld call for UT, and corresponding add_default for UT inside the - history_eddy conditional. -. diag_phys_writeout_dry - - add calculation and outfld call for UT -. diag_init_moist - - add addfld call for UQ, and corresponding add_default for UQ inside the - history_eddy conditional. -. diag_phys_writeout_moist - - add calculation and outfld call for UQ - -src/physics/cam/microp_aero.F90 -. microp_aero_run - - add condition that number of bulk aerosols must be > 0 before calling - ndrop_bam_run. - -src/physics/cam/nucleate_ice_cam.F90 -. nucleate_ice_cam_calc - - add conditionals so naer2 array not referenced when there are no - aerosols. - -src/physics/cam/vertical_diffusion.F90 -. vertical_diffusion_init - - fix conditional around add_default call for UFLX and VFLX so those - fields aren't added if they're not computed. - -src/physics/cam7/physpkg.F90 -. tphysbc - - add conditionals so modal aerosol calculations only called when modal - aerosols are present. - -If there were any failures reported from running test_driver.sh on any test -platform, and checkin with these failures has been OK'd by the gatekeeper, -then copy the lines from the td.*.status files for the failed tests to the -appropriate machine below. All failed tests must be justified. - -derecho/intel/aux_cam: - -derecho/nvhpc/aux_cam: - -izumi/nag/aux_cam: - -izumi/gnu/aux_cam: - -CAM tag used for the baseline comparison tests if different than previous -tag: - -Summarize any changes to answers: - -=============================================================== -=============================================================== - Tag name: cam6_4_047 Originator(s): jedwards4b, fvitt Date: 19 November 2024 From 244142f423276fa10b74520ac5dedbb572565c59 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 11:37:48 -0700 Subject: [PATCH 70/89] ChangeLog draft --- doc/ChangeLog | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 8ae657fda9..fac2f9ea5c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,59 @@ =============================================================== + +Tag name: cam6_4_051 +Originator(s): fvitt +Date: 2 Jan 2025 +One-line Summary: Updates to age of air tracers history output +Github PR URL: https://github.com/ESCOMP/CAM/pull/1198 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + + Changes to age of air output #1197 + . Output age of air tracers mix ratios to history as soon as the tendencies are update, + before the tracers are transported in the time loop + . Rename history field 'AOAMF' as 'AOA1' + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: + +List any changes to the defaults for the boundary datasets: + +Describe any substantial timing or memory changes: + +Code reviewed by: cacraigucar + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M src/physics/cam/aoa_tracers.F90 + - add outfld calls for AOA tracers + - rename 'AOAMF' as 'AOA1' + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: All PASS + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + DIFF ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes + DIFF SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee + DIFF SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s + - expected difference in AOA history fields , otherwise bit-for-bit unchanged + +Summarize any changes to answers: + Differences in AOA history fields, otherwise bit-for-bit unchanged + +=============================================================== +=============================================================== Tag name: cam6_4_050 Originator(s): jimmielin Date: 31 Dec 2024 From 7e9ce4b3057e6410e72231826e77f54256d9337b Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 13:57:20 -0700 Subject: [PATCH 71/89] ChangeLog update --- doc/ChangeLog | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index fac2f9ea5c..9e8a61063c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -39,15 +39,52 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: + PEND SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + + DIFF SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + + DIFF ERC_D_Ln9.f19_f19_mg17.QPX2000.derecho_intel.cam-outfrq3s + DIFF ERP_Ld3.f09_f09_mg17.FWHIST.derecho_intel.cam-reduced_hist1d + DIFF ERP_Ld3.ne30pg3_ne30pg3_mg17.FHISTC_MTt4s.derecho_intel.cam-outfrq1d_aoa + DIFF ERP_Lh12.f19_f19_mg17.FW4madSD.derecho_intel.cam-outfrq3h + DIFF ERP_Ln9.f19_f19_mg17.FWsc1850.derecho_intel.cam-outfrq9s + DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FCnudged.derecho_intel.cam-outfrq9s + DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s + DIFF ERS_Ln9.f09_f09_mg17.FX2000.derecho_intel.cam-outfrq9s + DIFF ERS_Ln9.f19_f19_mg17.FXSD.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f09_f09_mg17.FCts2nudged.derecho_intel.cam-outfrq9s_leapday + DIFF SMS_D_Ln9.f09_f09_mg17.FCvbsxHIST.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4 + DIFF SMS_D_Ln9.f19_f19_mg17.QPC2000climo.derecho_intel.cam-outfrq3s_usecase + DIFF SMS_D_Ln9.ne16_ne16_mg17.QPX2000.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.ne16pg3_ne16pg3_mg17.FX2000.derecho_intel.cam-outfrq9s + DIFF SMS_Ld1.f09_f09_mg17.FW2000climo.derecho_intel.cam-outfrq1d + DIFF SMS_Ld1.ne30pg3_ne30pg3_mg17.FC2010climo.derecho_intel.cam-outfrq1d + DIFF SMS_Ln9.f09_f09_mg17.FW1850.derecho_intel.cam-reduced_hist3s + DIFF SMS_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s_rrtmgp + - expected differences in AOA history fields, otherwise bit-for-bit unchanged + derecho/nvhpc/aux_cam: All PASS izumi/nag/aux_cam: + FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae + - pre-existing failure -- issue #670 + + DIFF ERC_D_Ln9.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s + DIFF SMS_D_Ln3.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s + DIFF SMS_D_Ln6.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem + - expected differences in AOA history fields, otherwise bit-for-bit unchanged izumi/gnu/aux_cam: DIFF ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes DIFF SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee DIFF SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s - - expected difference in AOA history fields , otherwise bit-for-bit unchanged + - expected differences in AOA history fields, otherwise bit-for-bit unchanged Summarize any changes to answers: Differences in AOA history fields, otherwise bit-for-bit unchanged From 286df594345331c7ffb64ac6376154b15923fe2f Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 14:00:06 -0700 Subject: [PATCH 72/89] ChangeLog update --- doc/ChangeLog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9e8a61063c..9822c0361f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -15,11 +15,11 @@ Purpose of changes (include the issue number and title text for each relevant Gi Describe any changes made to build system: N/A -Describe any changes made to the namelist: +Describe any changes made to the namelist: N/A -List any changes to the defaults for the boundary datasets: +List any changes to the defaults for the boundary datasets: N/A -Describe any substantial timing or memory changes: +Describe any substantial timing or memory changes: N/A Code reviewed by: cacraigucar From 189151b244f7af4595d08274d58b9fa07b2b807c Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 20:29:55 -0700 Subject: [PATCH 73/89] code review changes modified: bld/namelist_files/namelist_definition.xml modified: src/physics/cam/carma_flags_mod.F90 modified: src/physics/carma/cam/carma_intr.F90 --- bld/namelist_files/namelist_definition.xml | 5 ++- src/physics/cam/carma_flags_mod.F90 | 51 +++++++++++++++++++++- src/physics/carma/cam/carma_intr.F90 | 41 +++++++++++------ 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index d216f837f1..013d8eecfc 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -4480,7 +4480,10 @@ Default: none group="carma_nl" valid_values="ZhaoTurco,Vehkamaki" > Nucleation methods: ZhaoTurco - Zhao and Turco, JAS, V.26, No.5, 1995. + Zhao, J. and Turco, R., + Nucleation simulations in the wake of a jet aircraft in stratospheric flight, + J. Aerosol Sci., 26, 779-795, 1995, + https://doi.org/10.1016/0021-8502(95)00010-A Vehkamaki Vehkamaki, H., M. Kulmala, I. Napari, K.E.J. Lehtinen, C. Timmreck, M. Noppel and A. Laaksonen, 2002, diff --git a/src/physics/cam/carma_flags_mod.F90 b/src/physics/cam/carma_flags_mod.F90 index e583b43d90..2ed1fcc531 100644 --- a/src/physics/cam/carma_flags_mod.F90 +++ b/src/physics/cam/carma_flags_mod.F90 @@ -86,7 +86,7 @@ subroutine carma_readnl(nlfile) use cam_abortutils, only: endrun use namelist_utils, only: find_group_name - use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character + use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character, mpi_success use carma_model_flags_mod, only: carma_model_readnl ! args @@ -96,6 +96,7 @@ subroutine carma_readnl(nlfile) ! local vars integer :: unitn, ierr, i + character(len=*), parameter :: prefix = 'carma_readnl: ' ! read namelist for CARMA namelist /carma_nl/ & @@ -152,58 +153,104 @@ subroutine carma_readnl(nlfile) if (ierr == 0) then read(unitn, carma_nl, iostat=ierr) if (ierr /= 0) then - call endrun('carma_readnl: ERROR reading namelist') + call endrun(prefix//'ERROR reading namelist') end if end if close(unitn) end if call mpi_bcast (carma_flag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_flag') call mpi_bcast (carma_do_aerosol, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_aerosol') call mpi_bcast (carma_do_coremasscheck,1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_coremasscheck') call mpi_bcast (carma_do_cldliq, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cldliq') call mpi_bcast (carma_do_cldice, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cldice') call mpi_bcast (carma_do_clearsky, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_clearsky') call mpi_bcast (carma_do_cloudborne, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cloudborne') call mpi_bcast (carma_do_coag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_coag') call mpi_bcast (carma_do_detrain, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_detrain') call mpi_bcast (carma_do_drydep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_drydep') call mpi_bcast (carma_do_emission, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_emission') call mpi_bcast (carma_do_fixedinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_fixedinit') call mpi_bcast (carma_hetchem_feedback,1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_hetchem_feedback') call mpi_bcast (carma_rad_feedback, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_rad_feedback') call mpi_bcast (carma_do_explised, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_explised') call mpi_bcast (carma_do_budget_diags, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_budget_diags') call mpi_bcast (carma_do_package_diags,1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_package_diags') call mpi_bcast (carma_do_incloud, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_incloud') call mpi_bcast (carma_do_grow, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_grow') call mpi_bcast (carma_do_optics, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_optics') call mpi_bcast (carma_do_partialinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_partialinit') call mpi_bcast (carma_do_pheat, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_pheat') call mpi_bcast (carma_do_pheatatm, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_pheatatm') call mpi_bcast (carma_do_substep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_substep') call mpi_bcast (carma_do_thermo, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_thermo') call mpi_bcast (carma_do_wetdep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_wetdep') call mpi_bcast (carma_do_vdiff, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_vdiff') call mpi_bcast (carma_do_vtran, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_vtran') call mpi_bcast (carma_diags_file, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_diags_file') call mpi_bcast (carma_maxsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_maxsubsteps') call mpi_bcast (carma_minsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_minsubsteps') call mpi_bcast (carma_maxretries, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_maxretries') call mpi_bcast (carma_conmax, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_conmax') call mpi_bcast (carma_dgc_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_dgc_threshold') call mpi_bcast (carma_ds_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_ds_threshold') call mpi_bcast (carma_dt_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_dt_threshold') call mpi_bcast (carma_tstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_tstick') call mpi_bcast (carma_gsticki, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_gsticki') call mpi_bcast (carma_gstickl, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_gstickl') call mpi_bcast (carma_cstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_cstick') call mpi_bcast (carma_rhcrit, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_rhcrit') call mpi_bcast (carma_vf_const, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_vf_const') call mpi_bcast (carma_model, len(carma_model), mpi_character, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_model') call mpi_bcast (carma_sulfnuc_method, len(carma_sulfnuc_method), mpi_character, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_sulfnuc_method') call mpibcast (carma_diags_packages, len(carma_diags_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_diags_packages') call mpibcast (carma_debug_packages, len(carma_debug_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_debug_packages') carma_ndiagpkgs = 0 do i = 1, carma_maxdiags diff --git a/src/physics/carma/cam/carma_intr.F90 b/src/physics/carma/cam/carma_intr.F90 index 9e86637b0c..89f7f415d6 100644 --- a/src/physics/carma/cam/carma_intr.F90 +++ b/src/physics/carma/cam/carma_intr.F90 @@ -9,18 +9,30 @@ !! @version July 2009 module carma_intr - use carma_precision_mod - use carma_enums_mod - use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA - use carma_types_mod - use carma_flags_mod - use carma_model_mod - use carmaelement_mod - use carmagas_mod - use carmagroup_mod - use carmasolute_mod - use carmastate_mod - use carma_mod + use carma_precision_mod, only: f + use carma_enums_mod, only: I_OPTICS_FIXED, I_OPTICS_MIXED_CORESHELL, I_OPTICS_MIXED_VOLUME, & + I_OPTICS_MIXED_MAXWELL, I_OPTICS_SULFATE, I_CNSTTYPE_PROGNOSTIC, I_HYBRID + use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA, NWAVE, & + CARMA_NAME_LEN, CARMA_SHORT_NAME_LEN, PI, CAM_FILL, RGAS, RM2CGS, RAD2DEG, CLDFRC_INCLOUD + use carma_types_mod, only : carma_type, carmastate_type + use carma_flags_mod, only : carma_flag, carma_do_fixedinit, carma_model, carma_do_wetdep, carma_do_emission, & + carma_do_pheat, carma_do_substep, carma_do_thermo, carma_do_cldice, carma_diags_file, & + carma_do_grow, carma_ndebugpkgs, carma_conmax, carma_cstick, carma_tstick, carma_vf_const, carma_sulfnuc_method, & + carma_rhcrit, carma_rad_feedback, carma_minsubsteps, carma_maxsubsteps, carma_gstickl, carma_gsticki, & + carma_maxretries, carma_dt_threshold, carma_ds_threshold, carma_do_vtran, carma_do_vdiff, carma_do_pheatatm, & + carma_do_partialinit, carma_do_optics, carma_do_incloud, carma_do_explised, carma_do_drydep, carma_do_detrain, & + carma_do_coremasscheck, carma_do_coag, carma_do_clearsky, carma_do_cldliq, carma_do_aerosol, carma_dgc_threshold + + use carma_model_mod, only : NGAS, NBIN, NELEM, NGROUP, NMIE_WTP, NREFIDX, MIE_RH, NMIE_RH, NSOLUTE + use carma_model_mod, only : mie_rh, mie_wtp, is_convtran1, CARMAMODEL_DiagnoseBulk, CARMAMODEL_DiagnoseBins, & + CARMAMODEL_Detrain, CARMAMODEL_OutputDiagnostics, CARMAMODEL_CreateOpticsFile, CARMAMODEL_WetDeposition, & + CARMAMODEL_EmitParticle, CARMAMODEL_InitializeParticle, CARMAMODEL_DefineModel, CARMAMODEL_InitializeModel + use carmaelement_mod, only : CARMAELEMENT_Get + use carmagas_mod, only : CARMAGAS_Get + use carmagroup_mod, only : CARMAGROUP_Get + use carmastate_mod, only : CARMASTATE_CreateFromReference, CARMASTATE_SetGas, CARMASTATE_Step, CARMASTATE_GetBin, & + CARMASTATE_GetGas, CARMASTATE_GetState, CARMASTATE_Get, CARMASTATE_Create, CARMASTATE_SetBin, CARMASTATE_Destroy + use carma_mod, only : CARMA_Get, CARMA_Create, CARMA_Initialize, CARMA_Destroy use shr_kind_mod, only: r8 => shr_kind_r8 use spmd_utils, only: masterproc, mpicom @@ -35,6 +47,7 @@ module carma_intr use physics_buffer, only: physics_buffer_desc, pbuf_add_field, pbuf_old_tim_idx, & pbuf_get_index, pbuf_get_field, dtype_r8, pbuf_set_field use pio, only: var_desc_t + use radconstants, only: nlwbands, nswbands implicit none @@ -180,7 +193,7 @@ module carma_intr !! @author Chuck Bardeen !! @version May-2009 subroutine carma_register - use radconstants, only : nlwbands, get_sw_spectral_boundaries, get_lw_spectral_boundaries + use radconstants, only : get_sw_spectral_boundaries, get_lw_spectral_boundaries use cam_logfile, only : iulog use cam_control_mod, only : initial_run use physconst, only: gravit, p_rearth=>rearth, mwdry, mwh2o @@ -2608,7 +2621,7 @@ subroutine CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc) integer :: rhdim, lwdim, swdim, wtpdim integer :: rhvar, lwvar, swvar, wtp_var integer :: rwetvar - integer :: abs_lw_wtp_var, qabs_lw_wtp_var + integer :: abs_lw_wtp_var, qabs_lw_wtp_var integer :: ext_sw_wtp_var, ssa_sw_wtp_var, asm_sw_wtp_var, qext_sw_wtp_var integer :: omdim, andim, namedim integer :: omvar, anvar, namevar From 529e386216efbf2206025c59d17fa4f8235d16e9 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 3 Jan 2025 12:20:40 -0500 Subject: [PATCH 74/89] mods to namelist defaults and testlist --- bld/namelist_files/namelist_defaults_cam.xml | 3 --- cime_config/testdefs/testlist_cam.xml | 9 --------- doc/ChangeLog | 11 ++++++----- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 3d1643c4c8..1ac3b4d3a6 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -264,12 +264,9 @@ atm/cam/inic/se/ape_cam5_ne120np4_L30_c170419.nc atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L32_01-01-31_c221214.nc -atm/cam/inic/se/QPLT_L58_ne3pg3_c241127.nc -atm/cam/inic/se/cam6_QPC6_aqua_ne3pg3_mg37_L93_01_02_01_c240518.nc atm/cam/inic/se/ape_cam6_ne5np4_L32_c170517.nc atm/cam/inic/se/ape_cam6_ne16np4_L32_c170509.nc atm/cam/inic/se/ape_cam6_ne30np4_L32_c170509.nc -atm/cam/inic/se/QPLT_L58_ne30pg3_c241127.nc atm/cam/inic/se/ape_cam6_ne120np4_L32_c170908.nc atm/cam/inic/se/ape_cam6_ne240np4_L32_c170908.nc diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index c26abe5512..fc0903685b 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -1778,15 +1778,6 @@ - - - - - - - - - diff --git a/doc/ChangeLog b/doc/ChangeLog index 6ae50ee3d8..609f354f7a 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -63,9 +63,8 @@ List all files added and what they do: none List all existing files that have been modified, and describe the changes: bld/namelist_files/namelist_defaults_cam.xml -. replace current entry for ne3np4 L58 aquaplanet with - QPLT_L58_ne3pg3_c241127.nc. -. add new file for ne30np4 L58 aquaplanet. +. Remove ncdata files for nlev=58 and nlev=93 aquaplanet. Those files are + specified in the aquaplanet_cam7.xml use case file. bld/namelist_files/use_cases/aquaplanet_cam7.xml . use case file for QPLT and QPMT. Same as for QPC6 except: @@ -98,7 +97,7 @@ cime_config/testdefs/testlist_cam.xml . remove non-working DAE test . replace ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s by ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp -. Add ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq3s +. Add ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq9s . replace ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp by ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s . Add ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPMT.izumi_gnu.cam-outfrq9s @@ -161,7 +160,9 @@ izumi/gnu/aux_cam: CAM tag used for the baseline comparison tests if different than previous tag: -Summarize any changes to answers: +Summarize any changes to answers: BFB. Note however that a change in the + testmod definition for outfrq3s_cosp causes answer changes for tests + using that testmod. =============================================================== =============================================================== From 8582fd591a4f312332161a406d5089fa59b81919 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Sat, 4 Jan 2025 21:53:35 -0700 Subject: [PATCH 75/89] Fix bugs found with GNU regression tests. --- src/physics/cam/clubb_intr.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index a9878bc474..a9f25f0256 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2118,6 +2118,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & use cam_logfile, only: iulog use tropopause, only: tropopause_findChemTrop use time_manager, only: get_nstep, is_first_restart_step + use perf_mod, only: t_startf, t_stopf #ifdef CLUBB_SGS use hb_diff, only: pblintd @@ -2153,8 +2154,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & use macrop_driver, only: liquid_macro_tend use clubb_mf, only: integrate_mf - use perf_mod - #endif implicit none @@ -2192,12 +2191,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Local Variables ! ! ---------------------------------------------------- ! + integer :: i !Must be delcared outside "CLUBB_SGS" ifdef for det_s and det_ice zero-ing loops + #ifdef CLUBB_SGS type(physics_state) :: state1 ! Local copy of state variable type(physics_ptend) :: ptend_loc ! Local tendency from processes, added up to return as ptend_all - integer :: i, j, k, t, ixind, nadv + integer :: j, k, t, ixind, nadv integer :: ixcldice, ixcldliq, ixnumliq, ixnumice, ixq integer :: itim_old integer :: ncol, lchnk ! # of columns, and chunk identifier @@ -4478,7 +4479,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & dpdlfliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) dpdlfice(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) dpdlft(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) - detnliquid(:ncol,:pver) = ptend_loc%q(:,:,ixnumliq) + detnliquid(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixnumliq) call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) From 87cb0064d0a9deace7833f74ea4886a1824beecd Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Mon, 6 Jan 2025 10:15:23 -0700 Subject: [PATCH 76/89] Update ChangeLog. --- doc/ChangeLog | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9822c0361f..fb46dbae7a 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,64 @@ =============================================================== +Tag name: cam6_4_052 +Originator(s): huebleruwm, nusbaume +Date: 6 Jan 2025 +One-line Summary: clubb_intr GPUization +Github PR URL: https://github.com/ESCOMP/CAM/pull/1175 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + +Adds OpenACC directives to clubb_intr.F90 to enable GPU offloading of CLUBB. +BFB on CPUs, answer changing (but passes ECT) on GPUs. + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: N/A + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: nusbaume, katetc, cacraigucar + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M src/physics/cam/clubb_intr.F90 + - add OpenACC directives for GPU offloading + - add timer calls to evaulate performance + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + + DIFF SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + + PEND SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +derecho/nvhpc/aux_cam: + +ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: FAIL) + - Expected baseline failures due to non-BFB answer changes with new CLUBB GPU-offloading. + +izumi/nag/aux_cam: + FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: ALL PASS + +=============================================================== +=============================================================== + Tag name: cam6_4_051 Originator(s): fvitt Date: 2 Jan 2025 From 76ea3a47ff72ff6a9417c00f2b2d5054dba66fb2 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Tue, 7 Jan 2025 08:02:37 -0700 Subject: [PATCH 77/89] update ChangeLog --- doc/ChangeLog | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index fb46dbae7a..e105de2e94 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,138 @@ =============================================================== +Tag name: cam6_4_053 +Originator(s): fvitt +Date: 7 Jan 2025 +One-line Summary: Update CARMA base external tag +Github PR URL: https://github.com/ESCOMP/CAM/pull/1201 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + + Update CARMA sectional aerosol model base external to tag carma4_09 and update existing CARMA models accordingly + (Update CARMA base external #1181) + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: + - new carma_sulfnuc_method option + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: cacraigucar + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M .gitmodules + - update carma base tag + +M bld/build-namelist +M bld/namelist_files/namelist_definition.xml + - new carma_sulfnuc_method namelist option + +M cime_config/testdefs/testlist_cam.xml + - adjustments to carma tests + +M cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam + - remove carma_reftfile namelist setting + +M src/physics/cam/carma_flags_mod.F90 + - updates to carma runtime options + +M src/physics/cam/carma_intr.F90 +M src/physics/cam/physpkg.F90 +M src/physics/cam7/physpkg.F90 + - interface changes for including pbuf + +M src/physics/carma/cam/carma_constants_mod.F90 + +M src/physics/carma/cam/carma_intr.F90 + - add "only" to use statements + - add restart routines + - new diags flags + - many other updates needed for the development of trop_strat carma models + +M src/physics/carma/cam/carma_precision_mod.F90 +M src/physics/carma/models/bc_strat/carma_model_mod.F90 +M src/physics/carma/models/cirrus/carma_model_mod.F90 +M src/physics/carma/models/cirrus/growevapl.F90 +M src/physics/carma/models/cirrus_dust/carma_mod.F90 +M src/physics/carma/models/cirrus_dust/carma_model_mod.F90 +M src/physics/carma/models/cirrus_dust/growevapl.F90 +M src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 + - fix end module statements + - include missing real kind specifiers + +M src/physics/carma/models/dust/carma_model_mod.F90 +M src/physics/carma/models/meteor_impact/carma_model_mod.F90 +M src/physics/carma/models/meteor_smoke/carma_model_mod.F90 +M src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 +M src/physics/carma/models/pmc/carma_model_mod.F90 +M src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 +M src/physics/carma/models/sea_salt/carma_model_mod.F90 +M src/physics/carma/models/sulfate/carma_model_mod.F90 +M src/physics/carma/models/test_detrain/carma_model_mod.F90 +M src/physics/carma/models/test_growth/carma_model_mod.F90 +M src/physics/carma/models/test_passive/carma_model_mod.F90 +M src/physics/carma/models/test_radiative/carma_model_mod.F90 +M src/physics/carma/models/test_swelling/carma_model_mod.F90 +M src/physics/carma/models/test_tracers/carma_model_mod.F90 +M src/physics/carma/models/test_tracers2/carma_model_mod.F90 +M src/physics/carma/models/tholin/carma_model_mod.F90 + - update interfaces including optics calculations + - include missing real kind specifiers + +M test/system/TR8.sh + - include physics/carma and subdirectories in the r8 checks + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s COMPARE_base_rest + - pre-existing failure -- issue #856 + + FAIL SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie SETUP + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s SETUP + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +derecho/nvhpc/aux_cam: + FAIL ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default COMPARE_base_rest + - pre-existing failure -- issue #1220 + +izumi/nag/aux_cam: + FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae + - pre-existing failure -- issue #670 + + DIFF ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt + - expected differences due to updates to carma base code + +izumi/gnu/aux_cam: All PASS + +Summarize any changes to answers: + CARAM configurations change answers, otherwise bit-for-bit unchanged + +=============================================================== +=============================================================== + Tag name: cam6_4_052 Originator(s): huebleruwm, nusbaume Date: 6 Jan 2025 From 56ccdb0f56c2f8a0aeb7d9e6343d888b943738d5 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Tue, 7 Jan 2025 08:58:25 -0700 Subject: [PATCH 78/89] update ChangeLog --- doc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index e105de2e94..830edb9a3f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -61,6 +61,7 @@ M src/physics/cam7/physpkg.F90 - interface changes for including pbuf M src/physics/carma/cam/carma_constants_mod.F90 + - add MAXCLDAERDIAG M src/physics/carma/cam/carma_intr.F90 - add "only" to use statements From a5ed0a514c5e6a2e9b905565fcd1c4a4b60a55e7 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Tue, 7 Jan 2025 13:28:36 -0700 Subject: [PATCH 79/89] Update CICE tag to cesm3_cice6_6_0_6. --- .gitmodules | 2 +- cime | 2 +- src/atmos_phys | 2 +- src/physics/carma/base | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index e83e1f6a5c..752c3bf4f7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -186,7 +186,7 @@ fxDONOTUSEurl = https://github.com/NCAR/ParallelIO [submodule "cice"] path = components/cice url = https://github.com/ESCOMP/CESM_CICE -fxtag = cesm3_cice6_6_0_5 +fxtag = cesm3_cice6_6_0_6 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CESM_CICE diff --git a/cime b/cime index ac8e583108..b2f271b174 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit ac8e583108b1ce1f592a6f6436c71d6dc087f447 +Subproject commit b2f271b1742533715a05701b1bdd80a24bb2ad77 diff --git a/src/atmos_phys b/src/atmos_phys index c3de8468f7..67927f1511 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit c3de8468f7b245a939448f4ca6d3ef386584e92d +Subproject commit 67927f15113eb9c5d4a57f2276d67b8ad88c5149 diff --git a/src/physics/carma/base b/src/physics/carma/base index 67418505b4..bf165cd84e 160000 --- a/src/physics/carma/base +++ b/src/physics/carma/base @@ -1 +1 @@ -Subproject commit 67418505b48787bd305a50ffb581f98f0b466cba +Subproject commit bf165cd84ef94087d9a5669a5ad47838ab24c0ef From 9848f15a3c71ef78ec5f3fd7568adddb23f5644c Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 8 Jan 2025 14:54:19 -0700 Subject: [PATCH 80/89] use sim_year to determine stream_ndep settings; remove deprecated ndep_list modified: bld/build-namelist modified: bld/namelist_files/namelist_defaults_cam.xml modified: bld/namelist_files/namelist_definition.xml modified: bld/namelist_files/use_cases/1850_cam6.xml modified: bld/namelist_files/use_cases/1850_cam_lt.xml modified: bld/namelist_files/use_cases/1850_cam_mt.xml modified: bld/namelist_files/use_cases/2000_geoschem.xml modified: bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml modified: bld/namelist_files/use_cases/2010_cam6.xml modified: bld/namelist_files/use_cases/2010_geoschem.xml modified: bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml modified: bld/namelist_files/use_cases/hist_cam6.xml modified: bld/namelist_files/use_cases/hist_cam_lt.xml modified: bld/namelist_files/use_cases/hist_cam_mt.xml modified: bld/namelist_files/use_cases/hist_geoschem.xml modified: bld/namelist_files/use_cases/hist_geoschem_nudged.xml modified: bld/namelist_files/use_cases/hist_trop_strat_nudged_cam6.xml modified: bld/namelist_files/use_cases/hist_trop_strat_vbsext_cam6.xml modified: bld/namelist_files/use_cases/hist_trop_strat_vbsfire_cam6.xml modified: bld/namelist_files/use_cases/sd_cam6.xml modified: bld/namelist_files/use_cases/sd_trop_strat2_cam6.xml modified: bld/namelist_files/use_cases/sd_trop_strat_vbs_cam6.xml modified: bld/namelist_files/use_cases/sd_waccm_tsmlt_cam6.xml modified: bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml modified: bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml modified: bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml modified: bld/namelist_files/use_cases/waccm_tsmlt_1850_cam6.xml modified: bld/namelist_files/use_cases/waccm_tsmlt_2000_cam6.xml modified: bld/namelist_files/use_cases/waccm_tsmlt_2010_cam6.xml modified: bld/namelist_files/use_cases/waccm_tsmlt_hist_cam6.xml --- bld/build-namelist | 26 +++++++-------- bld/namelist_files/namelist_defaults_cam.xml | 20 +++++++++--- bld/namelist_files/namelist_definition.xml | 6 ---- bld/namelist_files/use_cases/1850_cam6.xml | 5 --- bld/namelist_files/use_cases/1850_cam_lt.xml | 8 ++--- bld/namelist_files/use_cases/1850_cam_mt.xml | 8 ++--- .../use_cases/2000_geoschem.xml | 3 -- .../use_cases/2000_trop_strat_vbs_cam6.xml | 2 -- bld/namelist_files/use_cases/2010_cam6.xml | 5 ++- .../use_cases/2010_geoschem.xml | 1 - .../use_cases/2010_trop_strat_vbs_cam6.xml | 2 -- bld/namelist_files/use_cases/hist_cam6.xml | 6 +--- bld/namelist_files/use_cases/hist_cam_lt.xml | 8 ++--- bld/namelist_files/use_cases/hist_cam_mt.xml | 8 ++--- .../use_cases/hist_geoschem.xml | 2 -- .../use_cases/hist_geoschem_nudged.xml | 2 -- .../use_cases/hist_trop_strat_nudged_cam6.xml | 2 -- .../use_cases/hist_trop_strat_vbsext_cam6.xml | 12 +++---- .../hist_trop_strat_vbsfire_cam6.xml | 2 -- bld/namelist_files/use_cases/sd_cam6.xml | 4 +-- .../use_cases/sd_trop_strat2_cam6.xml | 32 +++++++++---------- .../use_cases/sd_trop_strat_vbs_cam6.xml | 2 -- .../use_cases/sd_waccm_tsmlt_cam6.xml | 2 -- .../use_cases/waccm_ma_1850_cam6.xml | 2 -- .../use_cases/waccm_ma_hist_cam6.xml | 2 -- .../use_cases/waccm_sc_1850_cam6.xml | 8 ++--- .../use_cases/waccm_tsmlt_1850_cam6.xml | 2 -- .../use_cases/waccm_tsmlt_2000_cam6.xml | 2 -- .../use_cases/waccm_tsmlt_2010_cam6.xml | 2 -- .../use_cases/waccm_tsmlt_hist_cam6.xml | 2 -- 30 files changed, 63 insertions(+), 125 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index 22be75b310..7a66796964 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -509,19 +509,6 @@ if ($phys_mode_flags > 1) { my $simple_phys = 0; if ($adia_mode or $ideal_mode) { $simple_phys = 1; } -# Setup default ndep streams only if not simple_phys or aqua_mode and -# the chemistry cannot produce the nitrogen depostion fluxes -if (!($simple_phys or $aqua_mode)) { - my $chem_nitrodep = chem_has_species($cfg, 'NO') and chem_has_species($cfg, 'NH3'); - if (!$chem_nitrodep) { - add_default($nl, 'stream_ndep_data_filename'); - add_default($nl, 'stream_ndep_mesh_filename'); - add_default($nl, 'stream_ndep_year_first'); - add_default($nl, 'stream_ndep_year_last'); - add_default($nl, 'stream_ndep_year_align'); - } -} - # Single column mode my $scam = $cfg->get('scam'); my $scam_iop = $cfg->get('scam_iop'); @@ -710,6 +697,19 @@ if ($sim_year =~ /(\d+)-(\d+)/) { $sim_year_start = $1; } +# Setup default ndep streams only if not simple_phys or aqua_mode and +# the chemistry cannot produce the nitrogen depostion fluxes +if (!($simple_phys or $aqua_mode)) { + my $chem_nitrodep = chem_has_species($cfg, 'NO') and chem_has_species($cfg, 'NH3'); + if (!$chem_nitrodep) { + add_default($nl, 'stream_ndep_mesh_filename'); + add_default($nl, 'stream_ndep_data_filename', 'sim_year'=>$sim_year); + add_default($nl, 'stream_ndep_year_first', 'sim_year'=>$sim_year); + add_default($nl, 'stream_ndep_year_last', 'sim_year'=>$sim_year); + add_default($nl, 'stream_ndep_year_align', 'sim_year'=>$sim_year); + } +} + # Topography add_default($nl, 'use_topo_file'); my $use_topo_file = $nl->get_value('use_topo_file'); diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index ab2707290c..486b3a9fe0 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2061,11 +2061,23 @@ atm/cam/dst/dst_source1x1tuned-cam4-06202012.nc -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -2000 -2000 -1 + +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc + +2000 +1850 +1850 +2010 + +2000 +1850 +2015 +2010 + +1 +1850 .false. diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 185edfa81e..4aaa038224 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -7609,12 +7609,6 @@ Bubble-mediated sea-air transfer. See ocean_emis.F90 for details. Default: FALSE - -List of nitrogen deposition fluxes to be sent from CAM to surface models. -Default: set by build-namelist. - - Year first to use in nitrogen deposition stream data. diff --git a/bld/namelist_files/use_cases/1850_cam6.xml b/bld/namelist_files/use_cases/1850_cam6.xml index 14d0c61526..7f4cf09a5c 100644 --- a/bld/namelist_files/use_cases/1850_cam6.xml +++ b/bld/namelist_files/use_cases/1850_cam6.xml @@ -52,11 +52,6 @@ atm/cam/chem/emis/elev/H2O_emission_CH4_oxidationx2_elev_3DmonthlyL70_1850climoCMIP6piControl001_y21-50avg_c180802.nc -lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc -1850 -1850 -1 - 1850 diff --git a/bld/namelist_files/use_cases/1850_cam_lt.xml b/bld/namelist_files/use_cases/1850_cam_lt.xml index fe0fef33e6..d046c8bec7 100644 --- a/bld/namelist_files/use_cases/1850_cam_lt.xml +++ b/bld/namelist_files/use_cases/1850_cam_lt.xml @@ -61,11 +61,7 @@ CYCLICAL 1850 - -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -1850 -1850 -1 + +1850 diff --git a/bld/namelist_files/use_cases/1850_cam_mt.xml b/bld/namelist_files/use_cases/1850_cam_mt.xml index df05241070..68e7ca4a1a 100644 --- a/bld/namelist_files/use_cases/1850_cam_mt.xml +++ b/bld/namelist_files/use_cases/1850_cam_mt.xml @@ -56,11 +56,7 @@ CYCLICAL 1850 - -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -1850 -1850 -1 + +1850 diff --git a/bld/namelist_files/use_cases/2000_geoschem.xml b/bld/namelist_files/use_cases/2000_geoschem.xml index 3d2c5507b5..384d46b42a 100644 --- a/bld/namelist_files/use_cases/2000_geoschem.xml +++ b/bld/namelist_files/use_cases/2000_geoschem.xml @@ -36,9 +36,6 @@ - - - 1,30,365,240,240,480,365,73,30 diff --git a/bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml b/bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml index 47d97d6249..039685230f 100644 --- a/bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml +++ b/bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml @@ -131,8 +131,6 @@ 2000 -'noy', 'nhx' - 1,30,365,240,240,480,365,73,30 diff --git a/bld/namelist_files/use_cases/2010_cam6.xml b/bld/namelist_files/use_cases/2010_cam6.xml index d392d2b76e..641a8a8689 100644 --- a/bld/namelist_files/use_cases/2010_cam6.xml +++ b/bld/namelist_files/use_cases/2010_cam6.xml @@ -83,8 +83,7 @@ 'CYCLICAL' 2010 -2010 -2010 -1 + +2010 diff --git a/bld/namelist_files/use_cases/2010_geoschem.xml b/bld/namelist_files/use_cases/2010_geoschem.xml index b1b0f9f2eb..36c6eea697 100644 --- a/bld/namelist_files/use_cases/2010_geoschem.xml +++ b/bld/namelist_files/use_cases/2010_geoschem.xml @@ -34,7 +34,6 @@ - diff --git a/bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml b/bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml index a0b07f3248..7cd77b9b58 100644 --- a/bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml +++ b/bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml @@ -322,8 +322,6 @@ 2010 -'noy', 'nhx' - 1,30,365,240,240,480,365,73,30 diff --git a/bld/namelist_files/use_cases/hist_cam6.xml b/bld/namelist_files/use_cases/hist_cam6.xml index fff3618c07..9b79a04132 100644 --- a/bld/namelist_files/use_cases/hist_cam6.xml +++ b/bld/namelist_files/use_cases/hist_cam6.xml @@ -30,11 +30,7 @@ 'SERIAL' 'CO2','CH4','N2O','CFC11eq','CFC12' - 1850 - 2015 - 1850 - - 1850-2000 + 1850-2015 diff --git a/bld/namelist_files/use_cases/hist_cam_lt.xml b/bld/namelist_files/use_cases/hist_cam_lt.xml index a7cd6c0e9c..8f071a149b 100644 --- a/bld/namelist_files/use_cases/hist_cam_lt.xml +++ b/bld/namelist_files/use_cases/hist_cam_lt.xml @@ -42,11 +42,7 @@ INTERP_MISSING_MONTHS SERIAL - -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -1850 -2015 -1850 + +1850-2015 diff --git a/bld/namelist_files/use_cases/hist_cam_mt.xml b/bld/namelist_files/use_cases/hist_cam_mt.xml index 63b6691929..0c8e2e85fb 100644 --- a/bld/namelist_files/use_cases/hist_cam_mt.xml +++ b/bld/namelist_files/use_cases/hist_cam_mt.xml @@ -37,11 +37,7 @@ INTERP_MISSING_MONTHS SERIAL - -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -1850 -2015 -1850 + +1850-2015 diff --git a/bld/namelist_files/use_cases/hist_geoschem.xml b/bld/namelist_files/use_cases/hist_geoschem.xml index 1cfff4a8a9..2b3a158400 100644 --- a/bld/namelist_files/use_cases/hist_geoschem.xml +++ b/bld/namelist_files/use_cases/hist_geoschem.xml @@ -31,8 +31,6 @@ SERIAL -'noy', 'nhx' - 1,30,365,240,240,480,365,73,30 diff --git a/bld/namelist_files/use_cases/hist_geoschem_nudged.xml b/bld/namelist_files/use_cases/hist_geoschem_nudged.xml index 3c87bcb4fc..51105cd460 100644 --- a/bld/namelist_files/use_cases/hist_geoschem_nudged.xml +++ b/bld/namelist_files/use_cases/hist_geoschem_nudged.xml @@ -31,8 +31,6 @@ SERIAL -'noy', 'nhx' - .true. diff --git a/bld/namelist_files/use_cases/hist_trop_strat_nudged_cam6.xml b/bld/namelist_files/use_cases/hist_trop_strat_nudged_cam6.xml index ff2a92b3ef..026e329d7a 100644 --- a/bld/namelist_files/use_cases/hist_trop_strat_nudged_cam6.xml +++ b/bld/namelist_files/use_cases/hist_trop_strat_nudged_cam6.xml @@ -127,8 +127,6 @@ 'so4_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/emissions_ssp585/emissions-cmip6-ScenarioMIP_IAMC-REMIND-MAGPIE-ssp585-1-1_so4_a2_anthro-res_surface_mol_175001-210101_0.9x1.25_c20190224.nc' -'noy', 'nhx' - .true. 'atm/cam/met/nudging/MERRA2_fv09_32L/' diff --git a/bld/namelist_files/use_cases/hist_trop_strat_vbsext_cam6.xml b/bld/namelist_files/use_cases/hist_trop_strat_vbsext_cam6.xml index 38e1439ed0..1605081d6d 100644 --- a/bld/namelist_files/use_cases/hist_trop_strat_vbsext_cam6.xml +++ b/bld/namelist_files/use_cases/hist_trop_strat_vbsext_cam6.xml @@ -26,8 +26,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1,30,365,240,240,480,365,73,30 @@ -44,9 +42,9 @@ .false. .false. - + - 'CFC11STAR', 'AODDUST', 'AODDUST02', 'T', 'U', 'V', 'O3', 'OH', 'O3S', + 'CFC11STAR', 'AODDUST', 'AODDUST02', 'T', 'U', 'V', 'O3', 'OH', 'O3S', 'NO3', 'HO2', 'LNO_COL_PROD', 'NO2_CLXF', 'SFNO', 'SFNH3', 'BRO', 'CH3CL', 'CLO', 'CO2', 'HCL', 'HO2', 'HOCL', 'H2O', 'PHIS', 'Z3', 'BENZENE', 'C2H2', 'C2H4', 'C2H6', 'C3H8', 'CCL4', 'CFC11', 'CFC113', @@ -85,14 +83,14 @@ 'AODNIRstdn', 'AODUVstdn', 'AODdn_accum', 'AODdn_coarse', 'AODdnDUST01', 'AODdnDUST02', 'AODdnDUST03', 'AODVISstdn', 'AODUVstdn', 'AODNIRstdn', 'AODNIRstdn', 'AODVISdn', 'AODUVdn', 'EXTINCTdn', 'EXTxASYMdn', 'EXTINCTNIRdn', 'EXTINCTUVdn', 'WD_NC4CH2OH', 'WD_NC4CHO', 'WD_NDEP', 'WD_NH3', 'WD_NH4', 'WD_NHDEP', - 'WD_NOA', 'WD_NTERPOOH', 'WD_ONITR', 'WD_PHENOOH', 'WD_POOH', 'WD_ROOH', 'WD_SO2', + 'WD_NOA', 'WD_NTERPOOH', 'WD_ONITR', 'WD_PHENOOH', 'WD_POOH', 'WD_ROOH', 'WD_SO2', 'WD_SOAGbb0', 'WD_SOAGbb1', 'WD_SOAGbb2', 'WD_SOAGbb3', 'WD_SOAGbb4', 'WD_SOAGbg0', 'WD_SOAGbg1', 'WD_SOAGbg2', 'WD_SOAGbg3', 'WD_SOAGbg4', 'WD_SOAGff0', 'WD_SOAGff1', 'WD_SOAGff2', 'WD_SOAGff3', 'WD_SOAGff4', 'WD_SVOCbb','WD_SVOCff', 'WD_TERP2OOH', 'WD_TERPNIT', 'WD_TERPOOH', - 'DF_CO', 'DF_GLYALD', + 'DF_CO', 'DF_GLYALD', 'dry_deposition_NHx_as_N', 'DF_NH3', 'DF_NH4', 'DF_NO', 'DF_NO2', 'DF_NOA', 'DF_NTERPOOH', 'DF_O3', - 'DF_ONITR', 'DF_PAN', 'DF_PHENOOH', 'DF_POOH', 'DF_ROOH', 'DF_SO2', + 'DF_ONITR', 'DF_PAN', 'DF_PHENOOH', 'DF_POOH', 'DF_ROOH', 'DF_SO2', 'DF_SOAGbb0', 'DF_SOAGbb1', 'DF_SOAGbb2', 'DF_SOAGbb3', 'DF_SOAGbb4', 'DF_SOAGbg0', 'DF_SOAGbg1', 'DF_SOAGbg2', 'DF_SOAGbg3', 'DF_SOAGbg4', 'DF_SOAGff0', 'DF_SOAGff1', 'DF_SOAGff2', 'DF_SOAGff3', 'DF_SOAGff4', 'DF_SVOCbb','DF_SVOCff', 'DF_TERP2OOH', 'DF_TERPNIT', 'DF_TERPOOH', 'DF_TERPROD1', diff --git a/bld/namelist_files/use_cases/hist_trop_strat_vbsfire_cam6.xml b/bld/namelist_files/use_cases/hist_trop_strat_vbsfire_cam6.xml index 7219cf0322..791b6f3737 100644 --- a/bld/namelist_files/use_cases/hist_trop_strat_vbsfire_cam6.xml +++ b/bld/namelist_files/use_cases/hist_trop_strat_vbsfire_cam6.xml @@ -67,8 +67,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1,30,365,240,240,480,365,73,30 diff --git a/bld/namelist_files/use_cases/sd_cam6.xml b/bld/namelist_files/use_cases/sd_cam6.xml index 9a89255e88..2e81857089 100644 --- a/bld/namelist_files/use_cases/sd_cam6.xml +++ b/bld/namelist_files/use_cases/sd_cam6.xml @@ -36,8 +36,6 @@ 'SERIAL' 'CO2','CH4','N2O','CFC11eq','CFC12' - 1850 - 2015 - 1850 + 1850-2015 diff --git a/bld/namelist_files/use_cases/sd_trop_strat2_cam6.xml b/bld/namelist_files/use_cases/sd_trop_strat2_cam6.xml index 4075ad584c..4d32182f8a 100644 --- a/bld/namelist_files/use_cases/sd_trop_strat2_cam6.xml +++ b/bld/namelist_files/use_cases/sd_trop_strat2_cam6.xml @@ -31,8 +31,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1, 1 @@ -49,7 +47,7 @@ .false. .false. - + 'CFC11STAR', 'AODDUST', 'AODDUST02', 'T', 'U', 'V', 'O3', 'OH', 'NO3', 'HO2', 'LNO_COL_PROD', 'NO2_CLXF', 'SFNO', 'SFNH3', 'BRO', 'CH3CL', @@ -161,46 +159,46 @@ 'DF_BIGALD4', 'DF_BIGALK', 'DF_BIGENE', 'DF_BZALD', 'DF_C2H2', 'DF_C2H4', 'DF_C2H6', 'DF_C3H6', 'DF_C3H8', 'DF_CRESOL', 'DF_DMS', 'DF_GLYOXAL', 'DF_ISOP', 'DF_MACR', 'DF_MEK', 'DF_MVK', 'DF_N2O5', 'DF_PBZNIT', 'DF_PHENOL', 'DF_TEPOMUC', 'DF_TOLUENE', 'DF_XYLENES', 'DF_XYLOL', - 'WD_BCARY', 'WD_BENZENE', 'WD_BEPOMUC', 'WD_BIGALD1', 'WD_BIGALD2', 'WD_BIGALD3', 'WD_BIGALD4', + 'WD_BCARY', 'WD_BENZENE', 'WD_BEPOMUC', 'WD_BIGALD1', 'WD_BIGALD2', 'WD_BIGALD3', 'WD_BIGALD4', 'WD_BIGALK', 'WD_BIGENE', 'WD_BZALD', - 'WD_C2H2', 'WD_C2H4', 'WD_C2H6', 'WD_C3H6', 'WD_C3H8', 'WD_CO', 'WD_CRESOL', 'WD_DMS', 'WD_GLYOXAL', 'WD_ISOP', + 'WD_C2H2', 'WD_C2H4', 'WD_C2H6', 'WD_C3H6', 'WD_C3H8', 'WD_CO', 'WD_CRESOL', 'WD_DMS', 'WD_GLYOXAL', 'WD_ISOP', 'WD_MEK', 'WD_MPAN', 'WD_N2O5', 'WD_NO', 'WD_NO2', 'WD_PAN', 'WD_PBZNIT', 'WD_PHENOL', 'WD_TEPOMUC','WD_TOLUENE', 'WD_XYLENES', 'WD_XYLOL' 'MEG_APIN','MEG_BPIN','MEG_LIMON','MEG_MYRC', - 'ISOPFDN', 'ISOPFNP', 'ISOPN3B', 'ISOPN2B', 'ISOPN1D', 'ISOPN4D', + 'ISOPFDN', 'ISOPFNP', 'ISOPN3B', 'ISOPN2B', 'ISOPN1D', 'ISOPN4D', 'ISOPNBNO3', 'ISOPNOOHB', 'ISOPNOOHD', 'INHEB','INHED', 'HPALD1','HPALD4','ISOPHFP', - 'MVKN', 'MACRN', 'HMHP', 'NO3CH2CHO', 'HYPERACET', 'HCOCH2OOH', + 'MVKN', 'MACRN', 'HMHP', 'NO3CH2CHO', 'HYPERACET', 'HCOCH2OOH', 'DHPMPAL', 'MVKOOH', 'ISOPOH', 'HPALDB1C','HPALDB4C','ICHE','ISOPFDNC','ISOPFNC', - 'TERPNT', 'TERPNS','TERPNT1', 'TERPNS1', 'TERPNPT', 'TERPNPS', 'TERPNPT1', + 'TERPNT', 'TERPNS','TERPNT1', 'TERPNS1', 'TERPNPT', 'TERPNPS', 'TERPNPT1', 'TERPNPS1', 'TERPFDN', 'SQTN', 'TERPHFN', - 'TERP1OOH', 'TERPDHDP', 'TERPF2', 'TERPF1', 'TERPA', 'TERPA2', 'TERPK', 'TERPAPAN', + 'TERP1OOH', 'TERPDHDP', 'TERPF2', 'TERPF1', 'TERPA', 'TERPA2', 'TERPK', 'TERPAPAN', 'TERPACID', 'TERPA2PAN', 'TERPACID2','TERPACID3','TERPA3PAN','TERPOOHL','TERPA3', 'APIN','BPIN','LIMON','MYRC', 'DF_ISOPFDN', 'DF_ISOPFNP', 'DF_ISOPN3B', 'DF_ISOPN2B', 'DF_ISOPN1D', 'DF_ISOPN4D', 'DF_ISOPNBNO3', 'DF_ISOPNOOHB', 'DF_ISOPNOOHD', - 'DF_INHEB','DF_INHED', + 'DF_INHEB','DF_INHED', 'DF_HPALD1','DF_HPALD4','DF_ISOPHFP','DF_MVKN', 'DF_MACRN', 'DF_HMHP' 'DF_NO3CH2CHO', 'DF_HYPERACET', 'DF_HCOCH2OOH', 'DF_DHPMPAL', 'DF_MVKOOH', 'DF_ISOPOH', 'DF_HPALDB1C','DF_HPALDB4C','DF_ICHE','DF_ISOPFDNC','DF_ISOPFNC', - 'DF_TERPNT', 'DF_TERPNS','DF_TERPNT1', 'DF_TERPNS1', 'DF_TERPNPT', 'DF_TERPNPS', + 'DF_TERPNT', 'DF_TERPNS','DF_TERPNT1', 'DF_TERPNS1', 'DF_TERPNPT', 'DF_TERPNPS', 'DF_TERPNPT1', 'DF_TERPNPS1', 'DF_TERPFDN', 'DF_SQTN', 'DF_TERPHFN', - 'DF_TERP1OOH', 'DF_TERPDHDP', 'DF_TERPF2', 'DF_TERPF1', 'DF_TERPA', - 'DF_TERPA2', 'DF_TERPK', 'DF_TERPAPAN', 'DF_TERPACID', 'DF_TERPA2PAN', + 'DF_TERP1OOH', 'DF_TERPDHDP', 'DF_TERPF2', 'DF_TERPF1', 'DF_TERPA', + 'DF_TERPA2', 'DF_TERPK', 'DF_TERPAPAN', 'DF_TERPACID', 'DF_TERPA2PAN', 'DF_TERPACID2','DF_TERPACID3','DF_TERPA3PAN','DF_TERPOOHL','DF_TERPA3', 'DF_APIN','DF_BPIN','DF_LIMON','DF_MYRC', - 'WD_ISOPFDN', 'WD_ISOPFNP', 'WD_ISOPN3B', 'WD_ISOPN2B', 'WD_ISOPN1D', 'WD_ISOPN4D', + 'WD_ISOPFDN', 'WD_ISOPFNP', 'WD_ISOPN3B', 'WD_ISOPN2B', 'WD_ISOPN1D', 'WD_ISOPN4D', 'WD_ISOPNBNO3', 'WD_ISOPNOOHB', 'WD_ISOPNOOHD', - 'WD_INHEB','WD_INHED', + 'WD_INHEB','WD_INHED', 'WD_HPALD1','WD_HPALD4','WD_ISOPHFP','WD_MVKN', 'WD_MACRN', 'WD_HMHP' 'WD_NO3CH2CHO', 'WD_HYPERACET', 'WD_HCOCH2OOH', 'WD_DHPMPAL', 'WD_MVKOOH', 'WD_ISOPOH', 'WD_HPALDB1C','WD_HPALDB4C','WD_ICHE','WD_ISOPFDNC','WD_ISOPFNC', - 'WD_TERPNT', 'WD_TERPNS','WD_TERPNT1', 'WD_TERPNS1', 'WD_TERPNPT', 'WD_TERPNPS', + 'WD_TERPNT', 'WD_TERPNS','WD_TERPNT1', 'WD_TERPNS1', 'WD_TERPNPT', 'WD_TERPNPS', 'WD_TERPNPT1', 'WD_TERPNPS1', 'WD_TERPFDN', 'WD_SQTN', 'WD_TERPHFN', - 'WD_TERP1OOH', 'WD_TERPDHDP', 'WD_TERPF2', 'WD_TERPF1', 'WD_TERPA', + 'WD_TERP1OOH', 'WD_TERPDHDP', 'WD_TERPF2', 'WD_TERPF1', 'WD_TERPA', 'WD_TERPA2', 'WD_TERPK', 'WD_TERPAPAN','WD_TERPACID','WD_TERPA2PAN', 'WD_TERPACID2','WD_TERPACID3','WD_TERPA3PAN','WD_TERPOOHL','WD_TERPA3', 'WD_APIN','WD_BPIN','WD_LIMON','WD_MYRC' diff --git a/bld/namelist_files/use_cases/sd_trop_strat_vbs_cam6.xml b/bld/namelist_files/use_cases/sd_trop_strat_vbs_cam6.xml index 2fe99cb0eb..29c41758ca 100644 --- a/bld/namelist_files/use_cases/sd_trop_strat_vbs_cam6.xml +++ b/bld/namelist_files/use_cases/sd_trop_strat_vbs_cam6.xml @@ -41,8 +41,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1,30,365,240,240,480,365,73,30 diff --git a/bld/namelist_files/use_cases/sd_waccm_tsmlt_cam6.xml b/bld/namelist_files/use_cases/sd_waccm_tsmlt_cam6.xml index 9da740a7ae..f096415e31 100644 --- a/bld/namelist_files/use_cases/sd_waccm_tsmlt_cam6.xml +++ b/bld/namelist_files/use_cases/sd_waccm_tsmlt_cam6.xml @@ -47,8 +47,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1, 5, 20, 40, 120, 240, 365, 73, 365 diff --git a/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml index 24b55facc2..fbd7423680 100644 --- a/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml @@ -46,8 +46,6 @@ CYCLICAL 1850 -'noy', 'nhx' - 1, 30, 120, 240, 240, 480, 365, 73, 30 diff --git a/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml index 042a153fe4..3bc7948bce 100644 --- a/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml @@ -40,8 +40,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1, 30, 120, 240, 240, 480, 365, 73, 30 diff --git a/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml b/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml index 691150a417..77184615a1 100644 --- a/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml @@ -88,11 +88,7 @@ 'UTEND4', 'UTEND5', 'FRONTGF', 'FRONTGFA', 'EKGW', 'QNO', 'QRLNLTE', 'QRL_TOT', 'DUV', 'DVV', 'TTPXMLC' - -lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc -share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -1850 -1850 -1 + +1850 diff --git a/bld/namelist_files/use_cases/waccm_tsmlt_1850_cam6.xml b/bld/namelist_files/use_cases/waccm_tsmlt_1850_cam6.xml index 86e6af3bab..eefbf88163 100644 --- a/bld/namelist_files/use_cases/waccm_tsmlt_1850_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_tsmlt_1850_cam6.xml @@ -45,8 +45,6 @@ CYCLICAL 1850 -'noy', 'nhx' - 1, 5, 20, 40, 120, 240, 365, 73, 365 diff --git a/bld/namelist_files/use_cases/waccm_tsmlt_2000_cam6.xml b/bld/namelist_files/use_cases/waccm_tsmlt_2000_cam6.xml index efc485e990..fa5848ea40 100644 --- a/bld/namelist_files/use_cases/waccm_tsmlt_2000_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_tsmlt_2000_cam6.xml @@ -242,8 +242,6 @@ 'so4_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/CMIP6_emissions_2000climo_2deg/emissions-cmip6_so4_a2_anthro-res_surface_2000climo_1.9x2.5_c20200422.nc' -'noy', 'nhx' - 1, 5, 20, 40, 120, 240, 365, 73, 365 diff --git a/bld/namelist_files/use_cases/waccm_tsmlt_2010_cam6.xml b/bld/namelist_files/use_cases/waccm_tsmlt_2010_cam6.xml index fa65883ce1..ee6715c914 100644 --- a/bld/namelist_files/use_cases/waccm_tsmlt_2010_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_tsmlt_2010_cam6.xml @@ -142,8 +142,6 @@ 'so4_a2 -> $INPUTDATA_ROOT/atm/cam/chem/emis/CMIP6_emissions_2010climo/emissions-cmip6_so4_a2_anthro-res_surface_2010climo_0.9x1.25_c20180918.nc' -'noy', 'nhx' - 1, 5, 20, 40, 120, 240, 365, 73, 365 diff --git a/bld/namelist_files/use_cases/waccm_tsmlt_hist_cam6.xml b/bld/namelist_files/use_cases/waccm_tsmlt_hist_cam6.xml index 00fb808a52..623d08bc95 100644 --- a/bld/namelist_files/use_cases/waccm_tsmlt_hist_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_tsmlt_hist_cam6.xml @@ -38,8 +38,6 @@ INTERP_MISSING_MONTHS -'noy', 'nhx' - 1, 5, 20, 40, 120, 240, 365, 73, 365 From e106d4ff450bf1e6715f158ea1122c6561749f47 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 9 Jan 2025 08:32:04 -0700 Subject: [PATCH 81/89] update ChangeLog --- doc/ChangeLog | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index b535adc98e..5ebbb9ada8 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -12,7 +12,8 @@ Purpose of changes (include the issue number and title text for each relevant Gi surface models through the NUOPC mediator. This sets the nitrogen deposition fluxes to prescribed CDEP input stream fluxes if corresponding namelist options are set. Otherwise, the nitrogen deposition fluxes set to chemistry computed fluxes if the chemistry is capable - of providing the fluxes. (Github issue #1196) + of providing the fluxes. Deprecated ndep_list option in drv_flds_in has beed removed. + (Github issue #1196) Describe any changes made to build system: @@ -34,11 +35,13 @@ M bld/build-namelist - change how default ndep_stream namelist options are set . check if chemistry is capable of producing nitrogen deposition fluxes . set defaults only if not simple physics nor aqua-planet configuration + . pass sim_year to add_default to select appriate stream_ndep settings M bld/namelist_files/namelist_defaults_cam.xml - - default ndep_stream namelist settings for perpetual year 2000 configuration + - add default ndep_stream namelist settings M bld/namelist_files/namelist_definition.xml + - remote deprecated ndep_list namelist variable - updates to stream_ndep_* namelist descriptions M bld/namelist_files/use_cases/1850_cam_lt.xml @@ -48,7 +51,30 @@ M bld/namelist_files/use_cases/hist_cam_lt.xml M bld/namelist_files/use_cases/hist_cam_mt.xml M bld/namelist_files/use_cases/sd_cam6.xml M bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml - - stream_ndep_* namelist settings for use cases + - added sim_year + +M bld/namelist_files/use_cases/hist_cam6.xml + - changed sim_year to "1850-2015" + +M bld/namelist_files/use_cases/2000_geoschem.xml +M bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml +M bld/namelist_files/use_cases/2010_geoschem.xml +M bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml +M bld/namelist_files/use_cases/hist_geoschem.xml +M bld/namelist_files/use_cases/hist_geoschem_nudged.xml +M bld/namelist_files/use_cases/hist_trop_strat_nudged_cam6.xml +M bld/namelist_files/use_cases/hist_trop_strat_vbsext_cam6.xml +M bld/namelist_files/use_cases/hist_trop_strat_vbsfire_cam6.xml +M bld/namelist_files/use_cases/sd_trop_strat2_cam6.xml +M bld/namelist_files/use_cases/sd_trop_strat_vbs_cam6.xml +M bld/namelist_files/use_cases/sd_waccm_tsmlt_cam6.xml +M bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml +M bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml +M bld/namelist_files/use_cases/waccm_tsmlt_1850_cam6.xml +M bld/namelist_files/use_cases/waccm_tsmlt_2000_cam6.xml +M bld/namelist_files/use_cases/waccm_tsmlt_2010_cam6.xml +M bld/namelist_files/use_cases/waccm_tsmlt_hist_cam6.xml + - removed deprecated ndep_list M cime_config/buildnml - remove the use of CAM_STREAM_NDEP* xml vars to set stream_ndep* namelist options From 5f21959320ab834fdc2a6351153416daf170d425 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Thu, 9 Jan 2025 09:22:22 -0700 Subject: [PATCH 82/89] Finalize ChangeLog and update submodules from previous PRs. --- cime | 2 +- components/cice | 2 +- doc/ChangeLog | 29 ++++++++++++++++++++++++++++- src/atmos_phys | 2 +- src/physics/carma/base | 2 +- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/cime b/cime index b2f271b174..ac8e583108 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit b2f271b1742533715a05701b1bdd80a24bb2ad77 +Subproject commit ac8e583108b1ce1f592a6f6436c71d6dc087f447 diff --git a/components/cice b/components/cice index 787d3ccf3b..e51ab1d3f1 160000 --- a/components/cice +++ b/components/cice @@ -1 +1 @@ -Subproject commit 787d3ccf3b242214b0add3e474672f0609efcf2d +Subproject commit e51ab1d3f12ae2959b7df978f77dc5a1ee0181d3 diff --git a/doc/ChangeLog b/doc/ChangeLog index 6698551623..87cb50a54a 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -2,7 +2,7 @@ Tag name: cam6_4_054 Originator(s): nusbaume -Date: 7 Jan 2025 +Date: 9 Jan 2025 One-line Summary: Revert t_sfc limiter in RRTMGP Github PR URL: https://github.com/ESCOMP/CAM/pull/1211 @@ -39,14 +39,41 @@ platform, and checkin with these failures has been OK'd by the gatekeeper, then copy the lines from the td.*.status files for the failed tests to the appropriate machine below. All failed tests must be justified. +ALL F-compset answers changed (DIFF) due to the new CICE tag. + +Also any tests with RRTMGP will also have answer changes due +to the removal of the surface temperature limiter. + derecho/intel/aux_cam: + All F-compset tests + -NLCOMP and baseline DIFF failures due to the new CICE tag and t_sfc changes + + ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) + - pre-existing failure -- issue #856 + + SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) + SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + derecho/nvhpc/aux_cam: + ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: FAIL) + - pre-existing failure -- issue #1220 + - also had NLCOMP and baseline DIFF failures due to the new CICE tag and t_sfc changes. + izumi/nag/aux_cam: + DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure -- issue #670 + izumi/gnu/aux_cam: + ERP_D_Ln9.ne3pg3_ne3pg3_mg37.FLTHIST.izumi_gnu.cam-outfrq9s (Overall: DIFF) + ERS_Ln9_P24x1.mpasa480_mpasa480.F2000climo.izumi_gnu.cam-outfrq9s_mpasa480 (Overall: DIFF) + SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: DIFF) + - NLCOMP and baseline DIFF failures due to the new CICE tag and t_sfc changes. + CAM tag used for the baseline comparison tests if different than previous tag: diff --git a/src/atmos_phys b/src/atmos_phys index 67927f1511..c3de8468f7 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 67927f15113eb9c5d4a57f2276d67b8ad88c5149 +Subproject commit c3de8468f7b245a939448f4ca6d3ef386584e92d diff --git a/src/physics/carma/base b/src/physics/carma/base index bf165cd84e..67418505b4 160000 --- a/src/physics/carma/base +++ b/src/physics/carma/base @@ -1 +1 @@ -Subproject commit bf165cd84ef94087d9a5669a5ad47838ab24c0ef +Subproject commit 67418505b48787bd305a50ffb581f98f0b466cba From b30e9485906eabc06e59d6d4d09eb0e4a8ee7006 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 9 Jan 2025 12:43:11 -0700 Subject: [PATCH 83/89] add sim_year valid values of 2010 and 1850-2015 modified: bld/namelist_files/namelist_definition.xml --- bld/namelist_files/namelist_definition.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 4aaa038224..86f993a93d 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -8763,7 +8763,7 @@ Default: "." + group="camexp" valid_values="1850,2000,2010,1850-2000,1850-2015"> This varible is only used internally by build-namelist to determine appropriate defaults for climatological or transient forcing datasets. Default: set by build-namelist. From 22e9efeed49ab397e63d3f007edd6693214dbb0b Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Fri, 10 Jan 2025 11:46:08 -0500 Subject: [PATCH 84/89] add QPLT and QPMT tests to prealpha category --- cime_config/testdefs/testlist_cam.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index 600436da24..d0789ac1f3 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -202,6 +202,7 @@ + @@ -220,6 +221,7 @@ + From 27f78e8f42a90894ddb97bd73dcd95d925d88707 Mon Sep 17 00:00:00 2001 From: Brian Eaton Date: Mon, 13 Jan 2025 10:30:39 -0500 Subject: [PATCH 85/89] update ChangeLog --- doc/ChangeLog | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 59fa406cf4..625bc0dbbb 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,8 +1,8 @@ =============================================================== -Tag name: +Tag name: cam6_4_055 Originator(s): eaton -Date: +Date: 13 January 2025 One-line Summary: Add QPLT and QPMT compsets, plus misc. Github PR URL: https://github.com/ESCOMP/CAM/pull/1203 @@ -48,7 +48,7 @@ List any changes to the defaults for the boundary datasets: Describe any substantial timing or memory changes: n/a -Code reviewed by: +Code reviewed by: cacraig List all files eliminated: @@ -151,17 +151,47 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: +ERC_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq3s_cosp (Overall: DIFF) +- diffs due to changing the test definition (in outfrq3s_cosp) so that the use case file, + aquaplanet_cam6.xml, is no longer ignored. This changes answers. + +ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp (Overall: DIFF) +ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq9s (Overall: DIFF) +- There are no baselines for these new tests. + +ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) +- pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + +SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) +SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) +- pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + derecho/nvhpc/aux_cam: +ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: FAIL) +- pre-existing failure -- issue #1220 + izumi/nag/aux_cam: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: DIFF) details: +- diffs due to changing the test definition (in outfrq3s_cosp) so that the use case file, + aquaplanet_cam5.xml, is no longer ignored. This changes answers. + izumi/gnu/aux_cam: +ERC_D_Ln9.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: DIFF) +- Diff is due to the new diagnostic fields UT and UQ being included in the + test. Otherwise the run is identical with the baseline. + +ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s (Overall: DIFF) +ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPMT.izumi_gnu.cam-outfrq9s (Overall: DIFF) +- There are no baselines for these new tests. + CAM tag used for the baseline comparison tests if different than previous tag: Summarize any changes to answers: BFB. Note however that a change in the - testmod definition for outfrq3s_cosp causes answer changes for tests + test definition for outfrq3s_cosp causes answer changes for tests using that testmod. =============================================================== From 450312bd22f091613c754a761a56dfcd89976561 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 15 Jan 2025 09:04:39 -0700 Subject: [PATCH 86/89] Add sim_year to geoschem use case files; ChangeLog updates modified: bld/build-namelist modified: bld/namelist_files/use_cases/2010_geoschem.xml modified: bld/namelist_files/use_cases/hist_geoschem.xml modified: bld/namelist_files/use_cases/hist_geoschem_nudged.xml modified: doc/ChangeLog --- bld/build-namelist | 2 +- bld/namelist_files/use_cases/2010_geoschem.xml | 2 ++ bld/namelist_files/use_cases/hist_geoschem.xml | 2 ++ .../use_cases/hist_geoschem_nudged.xml | 2 ++ doc/ChangeLog | 12 ++++++++++-- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/bld/build-namelist b/bld/build-namelist index 7a66796964..6c14b26bbd 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -701,7 +701,7 @@ if ($sim_year =~ /(\d+)-(\d+)/) { # the chemistry cannot produce the nitrogen depostion fluxes if (!($simple_phys or $aqua_mode)) { my $chem_nitrodep = chem_has_species($cfg, 'NO') and chem_has_species($cfg, 'NH3'); - if (!$chem_nitrodep) { + if ((!$chem_nitrodep) or ($chem =~ /geoschem/)) { add_default($nl, 'stream_ndep_mesh_filename'); add_default($nl, 'stream_ndep_data_filename', 'sim_year'=>$sim_year); add_default($nl, 'stream_ndep_year_first', 'sim_year'=>$sim_year); diff --git a/bld/namelist_files/use_cases/2010_geoschem.xml b/bld/namelist_files/use_cases/2010_geoschem.xml index 36c6eea697..8f50e0321d 100644 --- a/bld/namelist_files/use_cases/2010_geoschem.xml +++ b/bld/namelist_files/use_cases/2010_geoschem.xml @@ -165,4 +165,6 @@ 'so4_a3', +2010 + diff --git a/bld/namelist_files/use_cases/hist_geoschem.xml b/bld/namelist_files/use_cases/hist_geoschem.xml index 2b3a158400..587ec4c1a4 100644 --- a/bld/namelist_files/use_cases/hist_geoschem.xml +++ b/bld/namelist_files/use_cases/hist_geoschem.xml @@ -161,4 +161,6 @@ 'so4_a3', +1850-2015 + diff --git a/bld/namelist_files/use_cases/hist_geoschem_nudged.xml b/bld/namelist_files/use_cases/hist_geoschem_nudged.xml index 51105cd460..6d6e94c6c5 100644 --- a/bld/namelist_files/use_cases/hist_geoschem_nudged.xml +++ b/bld/namelist_files/use_cases/hist_geoschem_nudged.xml @@ -216,4 +216,6 @@ 'so4_a3', +1850-2015 + diff --git a/doc/ChangeLog b/doc/ChangeLog index 5ebbb9ada8..18463609ac 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -12,9 +12,12 @@ Purpose of changes (include the issue number and title text for each relevant Gi surface models through the NUOPC mediator. This sets the nitrogen deposition fluxes to prescribed CDEP input stream fluxes if corresponding namelist options are set. Otherwise, the nitrogen deposition fluxes set to chemistry computed fluxes if the chemistry is capable - of providing the fluxes. Deprecated ndep_list option in drv_flds_in has beed removed. + of providing the fluxes. Deprecated ndep_list option in drv_flds_in has been removed. (Github issue #1196) + Currently there are no SSP scenario type compsets in CESM3 that use CAM atmosphere component. + Therefore, the specifications of the NDEP stream files for the SSP compsets are carried forward. + Describe any changes made to build system: Describe any changes made to the namelist: @@ -56,9 +59,14 @@ M bld/namelist_files/use_cases/waccm_sc_1850_cam6.xml M bld/namelist_files/use_cases/hist_cam6.xml - changed sim_year to "1850-2015" +M bld/namelist_files/use_cases/2010_geoschem.xml +M bld/namelist_files/use_cases/hist_geoschem.xml +M bld/namelist_files/use_cases/hist_geoschem_nudged.xml + - added sim_year + - removed deprecated ndep_list + M bld/namelist_files/use_cases/2000_geoschem.xml M bld/namelist_files/use_cases/2000_trop_strat_vbs_cam6.xml -M bld/namelist_files/use_cases/2010_geoschem.xml M bld/namelist_files/use_cases/2010_trop_strat_vbs_cam6.xml M bld/namelist_files/use_cases/hist_geoschem.xml M bld/namelist_files/use_cases/hist_geoschem_nudged.xml From c819813d8713daa89fd72128164915a02aab1fd3 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 16 Jan 2025 09:13:48 -0700 Subject: [PATCH 87/89] adjust sim_years for co2_cycle file defaults modified: bld/namelist_files/namelist_defaults_cam.xml --- bld/namelist_files/namelist_defaults_cam.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index bf9105db4a..3dfdca36f2 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -690,13 +690,13 @@ atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_1.9x2.5_c20181011.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_1.9x2.5_c20181011.nc -atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_1.9x2.5_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_1.9x2.5_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_0.9x1.25_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_1.9x2.5_c20181011.nc +atm/cam/ggas/emissions-cmip6_CO2_anthro_surface_175001-201512_fv_1.9x2.5_c20181011.nc ac_CO2_filelist_175001-201512_fv_0.9x1.25_c20181011.txt ac_CO2_filelist_175001-201512_fv_1.9x2.5_c20181011.txt From fa37cb5e0cef6626ba89615ebe23d63ca975a197 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 16 Jan 2025 17:25:35 -0700 Subject: [PATCH 88/89] ChangeLog update --- doc/ChangeLog | 71 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 71107e68e2..a6428bdc91 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,10 +1,10 @@ =============================================================== -Tag name: cam6_4_??? +Tag name: cam6_4_056 Originator(s): fvitt Date: -One-line Summary: -Github PR URL: +One-line Summary: Nitrogen depostion fluxes to surface models +Github PR URL: https://github.com/ESCOMP/CAM/pull/1216 Purpose of changes (include the issue number and title text for each relevant GitHub issue): @@ -18,19 +18,21 @@ Purpose of changes (include the issue number and title text for each relevant Gi Currently there are no SSP scenario type compsets in CESM3 that use CAM atmosphere component. Therefore, the specifications of the NDEP stream files for the SSP compsets are carried forward. -Describe any changes made to build system: +Describe any changes made to build system: N/A Describe any changes made to the namelist: -List any changes to the defaults for the boundary datasets: + Removed ndep_list drv_flds_in namelist variable -Describe any substantial timing or memory changes: +List any changes to the defaults for the boundary datasets: N/A -Code reviewed by: +Describe any substantial timing or memory changes: N/A -List all files eliminated: +Code reviewed by: brian-eaton, cacraigucar -List all files added and what they do: +List all files eliminated: N/A + +List all files added and what they do: N/A List all existing files that have been modified, and describe the changes: @@ -132,7 +134,58 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s + DIFF SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + + FAIL SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update + + NLFAIL ERC_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq3s_cosp + NLFAIL ERC_D_Ln9.f19_f19_mg17.QPMOZ.derecho_intel.cam-outfrq3s + NLFAIL ERC_D_Ln9.f19_f19_mg17.QPX2000.derecho_intel.cam-outfrq3s + NLFAIL ERC_D_Ln9.ne16_ne16_mg17.FADIAB.derecho_intel.cam-terminator + NLFAIL ERC_D_Ln9.ne16_ne16_mg17.QPC5HIST.derecho_intel.cam-outfrq3s_usecase + NLFAIL ERC_D_Ln9_P144x1.ne16pg3_ne16pg3_mg17.QPC6HIST.derecho_intel.cam-outfrq3s_ttrac_usecase + NLFAIL ERC_D_Ln9.T42_T42_mg17.FDABIP04.derecho_intel.cam-outfrq3s_usecase + NLFAIL ERC_D_Ln9.T42_T42_mg17.FHS94.derecho_intel.cam-outfrq3s_usecase + NLFAIL ERI_D_Ln18.f45_f45_mg37.QPC41850.derecho_intel.cam-co2rmp_usecase + NLFAIL ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPLT.derecho_intel.cam-outfrq3s_cosp + NLFAIL ERP_D_Ln9.ne30pg3_ne30pg3_mg17.QPMT.derecho_intel.cam-outfrq9s + NLFAIL ERP_D_Ln9_P64x2.f09_f09_mg17.QSC6.derecho_intel.cam-outfrq9s + NLFAIL ERS_Ln9.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.derecho_intel.cam-outfrq3s_refined + NLFAIL SCT_D_Ln7.ne3_ne3_mg37.QPC5.derecho_intel.cam-scm_prep + NLFAIL SCT_D_Ln7.T42_T42_mg17.QPC5.derecho_intel.cam-scm_prep + NLFAIL SMS_D_Ld2.f19_f19_mg17.QPC5HIST.derecho_intel.cam-volc_usecase + NLFAIL SMS_D_Ln9.f19_f19_mg17.QPC5M7.derecho_intel.cam-outfrq9s + NLFAIL SMS_D_Ln9.ne16_ne16_mg17.QPX2000.derecho_intel.cam-outfrq9s + - expected namelist compare failures due to removal of stream_ndep namelist opts + + DIFF ERP_Ld3.f09_f09_mg17.FWHIST.derecho_intel.cam-reduced_hist1d + DIFF ERP_Ld3.ne30pg3_ne30pg3_mg17.FHISTC_MTt4s.derecho_intel.cam-outfrq1d_aoa + DIFF ERP_Lh12.f19_f19_mg17.FW4madSD.derecho_intel.cam-outfrq3h + DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FCnudged.derecho_intel.cam-outfrq9s + DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s + DIFF ERS_Ln9.f09_f09_mg17.FX2000.derecho_intel.cam-outfrq9s + DIFF ERS_Ln9.f19_f19_mg17.FXSD.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f09_f09_mg17.FCts2nudged.derecho_intel.cam-outfrq9s_leapday + DIFF SMS_D_Ln9.f09_f09_mg17.FCvbsxHIST.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4 + DIFF SMS_D_Ln9.f19_f19_mg17.QPC2000climo.derecho_intel.cam-outfrq3s_usecase + DIFF SMS_D_Ln9.ne16pg3_ne16pg3_mg17.FX2000.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9_P1280x1.ne30pg3_ne30pg3_mg17.FHISTC_MTt1s.derecho_intel.cam-outfrq9s_Leung_dust + DIFF SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d + DIFF SMS_Ld1.f09_f09_mg17.FW2000climo.derecho_intel.cam-outfrq1d + DIFF SMS_Ld1.ne30pg3_ne30pg3_mg17.FC2010climo.derecho_intel.cam-outfrq1d + DIFF SMS_Ln9.f09_f09_mg17.FW1850.derecho_intel.cam-reduced_hist3s + DIFF SMS_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s_rrtmgp + - expected differences due to currections to ndep fluxes + derecho/nvhpc/aux_cam: + FAIL ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default COMPARE_base_rest + - pre-existing failure -- issue #1220 izumi/nag/aux_cam: From 4328f4e7fada667a33b20df7febd5d781a80b255 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 16 Jan 2025 19:22:20 -0700 Subject: [PATCH 89/89] ChangeLog update --- doc/ChangeLog | 94 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 23 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index a6428bdc91..d9a7a43b73 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -2,7 +2,7 @@ Tag name: cam6_4_056 Originator(s): fvitt -Date: +Date: 16 Jan 2025 One-line Summary: Nitrogen depostion fluxes to surface models Github PR URL: https://github.com/ESCOMP/CAM/pull/1216 @@ -184,36 +184,84 @@ derecho/intel/aux_cam: - expected differences due to currections to ndep fluxes derecho/nvhpc/aux_cam: + FAIL ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default COMPARE_base_rest - pre-existing failure -- issue #1220 izumi/nag/aux_cam: -izumi/gnu/aux_cam: - -CAM tag used for the baseline comparison tests if different than previous -tag: - -Summarize any changes to answers, i.e., -- what code configurations: -- what platforms/compilers: -- nature of change (roundoff; larger than roundoff but same climate; new - climate): - -If bitwise differences were observed, how did you show they were no worse -than roundoff? + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s + NLFAIL ERC_D_Ln9.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s + NLFAIL ERC_D_Ln9.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase + NLFAIL ERC_D_Ln9.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase + NLFAIL ERC_D_Ln9.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase + NLFAIL ERC_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac + NLFAIL ERC_D_Ln9.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase + NLFAIL ERI_D_Ln18.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac + NLFAIL ERI_D_Ln18.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 + NLFAIL ERI_D_Ln18.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic + NLFAIL ERI_D_Ln18.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic + NLFAIL ERP_Ln9.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf + NLFAIL ERS_Ln27.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s + NLFAIL ERS_Ln9.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s + NLFAIL PEM_D_Ln9.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s + NLFAIL PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 + NLFAIL PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 + NLFAIL PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 + NLFAIL PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 + NLFAIL PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 + NLFAIL PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 + NLFAIL SMS_D_Ln3.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s + NLFAIL SMS_D_Ln6.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem + NLFAIL SMS_D_Ln7.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm + NLFAIL SMS_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam + NLFAIL SMS_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba + NLFAIL SMS_D_Ln9_P1x1.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s + NLFAIL SMS_P48x1_D_Ln3.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase + NLFAIL SUB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s + NLFAIL TMC_D.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac + NLFAIL TMC_D.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 + - expected namelist compare failures due to removal of stream_ndep namelist opts -If this tag changes climate describe the run(s) done to evaluate the new -climate in enough detail that it(they) could be reproduced, i.e., -- source tag (all code used must be in the repository): -- platform/compilers: -- configure commandline: -- build-namelist command (or complete namelist): -- MSS location of output: +izumi/gnu/aux_cam: + NLFAIL ERC_D_Ln9.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag + NLFAIL ERC_D_Ln9.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s + NLFAIL ERC_D_Ln9.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 + NLFAIL ERC_D_Ln9.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba + NLFAIL ERC_D_Ln9.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s + NLFAIL ERC_D_Ln9.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s + NLFAIL ERI_D_Ln18.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp + NLFAIL ERP_D_Ln9.C48_C48_mg17.QPC6.izumi_gnu.cam-outfrq9s + NLFAIL ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPLT.izumi_gnu.cam-outfrq9s + NLFAIL ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPMT.izumi_gnu.cam-outfrq9s + NLFAIL ERP_Ln9.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s + NLFAIL ERP_Ln9.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s + NLFAIL ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes + NLFAIL PEM_D_Ln9.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s + NLFAIL PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 + NLFAIL PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 + NLFAIL PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 + NLFAIL SCT_D_Ln7.ne3_ne3_mg37.QPC6.izumi_gnu.cam-scm_prep_c6 + NLFAIL SCT_D_Ln7.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep + NLFAIL SCT_D_Ln7.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 + NLFAIL SMS_D_Ln3.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc + NLFAIL SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee + NLFAIL SMS_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac + - expected namelist compare failures due to removal of stream_ndep namelist opts -MSS location of control simulations used to validate new climate: + DIFF SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s + - expected differences due to currections to ndep fluxes -URL for AMWG diagnostics output used to validate new climate: +Summarize any changes to answers: bit-for-bit unchanged =============================================================== ===============================================================