From a6909e1eea7275c473ef625af7cda0e9b33467d4 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Mon, 9 Sep 2024 14:20:24 -0600 Subject: [PATCH] ESCOMP tag: cam6_4_031 Merge pull request #1131 from brian-eaton/misc05 cam6_4_031: fix issues #1108, #1106, #1058, #1051, #1050; merge PR#1101 ESCOMP commit: 9f0cb73a5f2c974ee7141b1bf2458da85a6f3b68 --- .../use_cases/aquaplanet_cam3.xml | 77 -- cime_config/buildnml | 4 +- doc/ChangeLog | 196 ++++ .../modal_aero/modal_aero_rename.F90 | 9 - src/chemistry/utils/prescribed_ozone.F90 | 9 +- src/control/cam_history.F90 | 84 +- src/control/cam_snapshot_common.F90 | 41 +- src/control/runtime_opts.F90 | 4 - src/dynamics/fv/cd_core.F90 | 4 +- src/dynamics/fv/dynamics_vars.F90 | 1 - src/dynamics/se/dycore/interpolate_mod.F90 | 8 +- src/physics/cam/cam3_aero_data.F90 | 1021 ----------------- src/physics/cam/cam3_ozone_data.F90 | 220 ---- src/physics/cam/convect_shallow.F90 | 2 +- src/physics/cam/eddy_diff.F90 | 17 +- src/physics/cam/eddy_diff_cam.F90 | 16 +- src/physics/cam/gw_common.F90 | 2 +- src/physics/cam/gw_drag.F90 | 32 +- src/physics/cam/physpkg.F90 | 26 - src/physics/cam/rk_stratiform.F90 | 28 +- src/physics/cam/uwshcu.F90 | 6 +- src/physics/cam/vertical_diffusion.F90 | 12 +- src/physics/cam/zm_conv_intr.F90 | 90 +- src/physics/camrt/radconstants.F90 | 2 +- src/physics/camrt/radlw.F90 | 6 +- src/physics/rrtmg/aer_src/rrtmg_sw_init.f90 | 4 - 26 files changed, 370 insertions(+), 1551 deletions(-) delete mode 100644 bld/namelist_files/use_cases/aquaplanet_cam3.xml delete mode 100644 src/physics/cam/cam3_aero_data.F90 delete mode 100644 src/physics/cam/cam3_ozone_data.F90 diff --git a/bld/namelist_files/use_cases/aquaplanet_cam3.xml b/bld/namelist_files/use_cases/aquaplanet_cam3.xml deleted file mode 100644 index 373b2ad18d..0000000000 --- a/bld/namelist_files/use_cases/aquaplanet_cam3.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - -300 -150 - - -0. -0. -0. -fixed_parameters - - - false - - -348.0e-6 -1650.0e-9 -306.0e-9 -280.e-12 -503.e-12 - - - .false. - - - 4.0e-4 - 16.0e-6 - 5.0e-6 - 0.910D0 - 0.700D0 - 0.070D0 - 500.0D0 - 0.140D0 - 500.0D0 - 25000.0D0 - 1800.0D0 - 1.0e-4 - 0.0040D0 - 0.0040D0 - 1.0E-6 - - - -1365.0 -/ - - -apeozone_cam3_5_54.nc -atm/cam/ozone -OZONE -CYCLICAL -1990 - - - - - -86164.10063718943 -6.37100e6 -9.79764 -28.96623324623746 -18.01618112892741 -1.846e3 -273.16 - -'A:Q:H2O', 'N:O2:O2', 'N:CO2:CO2', 'N:ozone:O3', 'N:N2O:N2O', 'N:CH4:CH4', 'N:CFC11:CFC11','N:CFC12:CFC12' - - - 0.5 - - - 0 - - diff --git a/cime_config/buildnml b/cime_config/buildnml index a077e13fcd..9c156b66d5 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -78,11 +78,11 @@ def buildnml(case, caseroot, compname): buildcpp = import_from_file("buildcpp", cmd) _ = buildcpp.buildcpp(case) except: - raise RuntimeError("CAM's 'buildcpp' script failed to run properly.") + logger.warning(" ...cam buildcpp exited with error") # Verify that we have a config_cache file (generated by the call to buildcpp) expect(os.path.isfile(filename), - " Missing config_cache.xml - cannot run build-namelist") + " Missing CAM's config_cache.xml - cannot run build-namelist") #-------------------------------------------------------------------- # Invoke cam build-namelist - output will go in $CASEROOT/Buildconf/camconf diff --git a/doc/ChangeLog b/doc/ChangeLog index 635389ba6d..b98e1d5fa9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,200 @@ +=============================================================== + +Tag name: cam6_4_031 +Originator(s): jedwards, eaton +Date: Sept 9, 2024 +One-line Summary: fix issues #1108, #1106, #1058, #1051, #1050; merge PR#1101 +Github PR URL: https://github.com/ESCOMP/CAM/pull/1131 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + +Issue #1108 - More robust logic in gw_drag.F90 when deep_scheme='off' +- Modify build-namelist to set use_gw_convect_dp=.false. when + deep_scheme='off'. In gw_drag::gw_tend check whether field TTEND_DP is + in the pbuf. If so then associate the ttend_dp pointer. If not then + allocate the ttend_dp pointer and set to zero. + +PR #1101 - improved fix for rh write performance +- reorder output fields. Merge Jim's PR into this one. + +Issue #1106 - Report an error if a user uses --model_top with anything other than cam7 +- configure reports this error, but the output in the log file gets + obscured by a stack traceback issued from buildnml which is not useful. + The fix implemented in buildnml replaces the "raise RuntimeError" call with + a warning message in the log file. Then, if a subsequent check for CAM's + config_cache.xml file fails, the execution is terminated by a call to + the CIME.utils "expect()" routine. + +Issue #1058 - Remove unused pbuf variable smaw +- Remove both smaw and turbtype from physics buffer. Neither is used. + Remove the calculation of smaw entirely. Calculation of turbtype + remains. It is used locally, and may be written to history file + (UW_turbtype). + +Issue #1051 - Bad logic in SE dycore "interpolate_vector" subroutines +- These subroutines are not currently used by CAM as they are restricted to + interpolating fields on the GLL grid. Fix the conditional logic and + update the endrun message. + +Issue #1050 - Remove CAM3 as a compset or configure option + +Describe any changes made to build system: + +Describe any changes made to the namelist: +. build-namelist now sets use_gw_convect_dp=.false. when deep_scheme='off'. + +List any changes to the defaults for the boundary datasets: + +Describe any substantial timing or memory changes: + +Code reviewed by: peverwhee, nusbaume + +List all files eliminated: + +bld/namelist_files/use_cases/aquaplanet_cam3.xml +src/physics/cam/cam3_aero_data.F90 +src/physics/cam/cam3_ozone_data.F90 + +List all files added and what they do: + +List all existing files that have been modified, and describe the changes: + +bld/build-namelist +. add check to set use_gw_convect_dp=.false. when deep_scheme='off'. +. remove cam3 conditionals +. remove variables cam3_ozone_data_on, cam3_aero_data_on, bndtvo, bndtvaer +. remove cam3 ozone and aerosols from rad_climate specification. +. remove cam3 aerosol deposition fluxes +. remove add_default for fcrit2 + +bld/configure +. remove cam3 as valid physics package + +bld/config_files/definition.xml +. remove cam3 as valid value for -phys + +bld/namelist_files/namelist_defaults_cam.xml +. remove cam3 bulk aerosol files +. remove cam3 setting for fv_fft_flt + +bld/namelist_files/namelist_definition.xml +. remove definitions for cam3_ozone_data_on, cam3_aero_data_on, bndtvo, + bndtvaer, ozncyc +. remove cam3 as valid value for cam_physpkg +. remove definition for fcrit2 + +cime_config/buildnml +. replace RuntimeError exception with message to logger. + +cime_config/config_compsets.xml +. remove QPC3 + +cime_config/config_component.xml +. remove regexp matches for _CAM30 + +src/chemistry/modal_aero/modal_aero_rename.F90 +. remove cam3 comments + +src/chemistry/utils/prescribed_ozone.F90 +. remove cam3 conditional + +src/control/cam_history.F90 +. The variables in the restart history files are reordered so that the nacs + variables are all written together rather than being next to their + corresponding fields. +src/control/cam_snapshot_common.F90 +. change npbuf_all from 327 to 314 +. fill_pbuf_info + - remove smaw, turbtype + - remove 11 fields: cam3_* + +src/control/runtime_opts.F90 +. remove refs to cam3_aero_data and cam3_ozone_data + +src/dynamics/fv/cd_core.F90 +src/dynamics/fv/dynamics_vars.F90 +. remove cam3 comments + +src/dynamics/se/dycore/interpolate_mod.F90 +. interpolate_vector2d and interpolate_vector3d + - fix conditional logic and clarify endrun message to indicate that the + input fields must be on the GLL grid. + +src/physics/cam/convect_shallow.F90 +. remove cam3 from conditional + +src/physics/cam/eddy_diff.F90 +. caleddy + - remove intent(out) arg sm_aw + +src/physics/cam/eddy_diff_cam.F90 +. eddy_diff_tend + - remove intent(out) args sm_aw and turbtype +. compute_eddy_diff + - remove intent(out) arg sm_aw + - remove intent(out) arg turbtype. use local storage for turbtype. + +src/physics/cam/gw_common.F90 +. remove cam3 comment + +src/physics/cam/gw_drag.F90 +. check that field TTEND_DP is in the pbuf before trying to associate the + pointer ttend_dp. If TTEND_DP is not in pbuf then allocate the ttend_dp + pointer and fill with zeros. +. remove fcrit2 from the namelist. Hardcode to 1.0 in GWBand call that + sets band_oro, just like all the other calls to GWBand. + +src/physics/cam/rk_stratiform.F90 +. remove cam3 from conditional + +src/physics/cam/uwshcu.F90 +. remove cam3 comment + +src/physics/cam/vertical_diffusion.F90 +. remove smaw and turbtype from physics buffer +. vertical_diffusion_tend + - remove smaw and turbtype as actual args in call to eddy_diff_tend + +src/physics/cam/zm_conv_intr.F90 +. remove cam3 conditional + +src/physics/camrt/radlw.F90 +. remove cam3 conditional + +src/physics/rrtmg/aer_src/rrtmg_sw_init.f90 +. remove cam3 comment + + +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: + + 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_P1280x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.derecho_intel.cam-outfrq9s + SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: PEND) + - pre-existing failures -- need fix in CLM external + +derecho/nvhpc/aux_cam: ALL PASS + +izumi/nag/aux_cam: + + DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure - issue #670 + +izumi/gnu/aux_cam: ALL PASS + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers: BFB + +=============================================================== =============================================================== Tag name: cam6_4_030 diff --git a/src/chemistry/modal_aero/modal_aero_rename.F90 b/src/chemistry/modal_aero/modal_aero_rename.F90 index 8a7d120f24..9ff3a2c87d 100644 --- a/src/chemistry/modal_aero/modal_aero_rename.F90 +++ b/src/chemistry/modal_aero/modal_aero_rename.F90 @@ -183,9 +183,6 @@ subroutine modal_aero_rename_sub( & real(r8), intent(inout) :: dqqcwdt(ncol,pver,pcnstxx) real(r8), intent(in) :: dqdt_other(ncol,pver,pcnstxx) ! tendencies for "other" continuous growth process - ! currently in cam3 - ! dqdt is from gas (h2so4, nh3) condensation - ! dqdt_other is from aqchem and soa ! *** NOTE ncol and pcnstxx dimensions real(r8), intent(in) :: dqqcwdt_other(ncol,pver,pcnstxx) logical, intent(inout) :: dotendrn(pcnstxx) ! identifies the species for which @@ -286,9 +283,6 @@ subroutine modal_aero_rename_no_acc_crs_sub( & real(r8), intent(inout) :: dqqcwdt(ncol,pver,pcnstxx) real(r8), intent(in) :: dqdt_other(ncol,pver,pcnstxx) ! tendencies for "other" continuous growth process - ! currently in cam3 - ! dqdt is from gas (h2so4, nh3) condensation - ! dqdt_other is from aqchem and soa ! *** NOTE ncol and pcnstxx dimensions real(r8), intent(in) :: dqqcwdt_other(ncol,pver,pcnstxx) logical, intent(inout) :: dotendrn(pcnstxx) ! identifies the species for which @@ -878,9 +872,6 @@ subroutine modal_aero_rename_acc_crs_sub( & real(r8), intent(inout) :: dqqcwdt(ncol,pver,pcnstxx) real(r8), intent(in) :: dqdt_other(ncol,pver,pcnstxx) ! tendencies for "other" continuous growth process - ! currently in cam3 - ! dqdt is from gas (h2so4, nh3) condensation - ! dqdt_other is from aqchem and soa ! *** NOTE ncol and pcnstxx dimensions real(r8), intent(in) :: dqqcwdt_other(ncol,pver,pcnstxx) logical, intent(inout) :: dotendrn(pcnstxx) ! identifies the species for which diff --git a/src/chemistry/utils/prescribed_ozone.F90 b/src/chemistry/utils/prescribed_ozone.F90 index 92a4ac84b4..cc82603025 100644 --- a/src/chemistry/utils/prescribed_ozone.F90 +++ b/src/chemistry/utils/prescribed_ozone.F90 @@ -215,13 +215,8 @@ subroutine prescribed_ozone_adv( state, pbuf2d) if( .not. has_prescribed_ozone ) return - if( cam_physpkg_is('cam3') .and. aqua_planet ) then - molmass = 48._r8 - amass = 28.9644_r8 - else - molmass = 47.9981995_r8 - amass = mwdry - end if + molmass = 47.9981995_r8 + amass = mwdry call advance_trcdata( fields, file, state, pbuf2d ) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 99fb9b3a0b..39222fc536 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -4694,7 +4694,6 @@ subroutine h_define (t, restart) num_hdims = 2 do i = 1, num_hdims dimindex(i) = header_info(1)%get_hdimid(i) - nacsdims(i) = header_info(1)%get_hdimid(i) end do else if (patch_output) then ! All patches for this variable should be on the same grid @@ -4720,7 +4719,6 @@ subroutine h_define (t, restart) num_hdims = header_info(grd)%num_hdims() do i = 1, num_hdims dimindex(i) = header_info(grd)%get_hdimid(i) - nacsdims(i) = header_info(grd)%get_hdimid(i) end do end if ! is_satfile @@ -4836,22 +4834,8 @@ subroutine h_define (t, restart) tape(t)%hlist(fld)%field%name) call cam_pio_handle_error(ierr, & 'h_define: cannot define basename for '//trim(fname_tmp)) - end if - - if (restart) then - ! For restart history files, we need to save accumulation counts - fname_tmp = trim(fname_tmp)//'_nacs' - if (.not. associated(tape(t)%hlist(fld)%nacs_varid)) then - allocate(tape(t)%hlist(fld)%nacs_varid) - end if - if (size(tape(t)%hlist(fld)%nacs, 1) > 1) then - call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_int, & - nacsdims(1:num_hdims), tape(t)%hlist(fld)%nacs_varid) - else - ! Save just one value representing all chunks - call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_int, & - tape(t)%hlist(fld)%nacs_varid) - end if + end if + if(restart) then ! for standard deviation if (associated(tape(t)%hlist(fld)%sbuf)) then fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name) @@ -4862,9 +4846,69 @@ subroutine h_define (t, restart) call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_double, & dimids_tmp(1:fdims), tape(t)%hlist(fld)%sbuf_varid) endif - end if - end do ! Loop over output patches + endif + end do ! Loop over output patches end do ! Loop over fields + if (restart) then + do fld = 1, nflds(t) + if(is_satfile(t)) then + num_hdims=0 + nfils(t)=1 + else if (interpolate) then + ! Interpolate can't use normal grid code since we are forcing fields + ! to use interpolate decomp + if (.not. allocated(header_info)) then + ! Safety check + call endrun('h_define: header_info not allocated') + end if + num_hdims = 2 + do i = 1, num_hdims + nacsdims(i) = header_info(1)%get_hdimid(i) + end do + else if (patch_output) then + ! All patches for this variable should be on the same grid + num_hdims = tape(t)%patches(1)%num_hdims(tape(t)%hlist(fld)%field%decomp_type) + else + ! Normal grid output + ! Find appropriate grid in header_info + if (.not. allocated(header_info)) then + ! Safety check + call endrun('h_define: header_info not allocated') + end if + grd = -1 + do i = 1, size(header_info) + if (header_info(i)%get_gridid() == tape(t)%hlist(fld)%field%decomp_type) then + grd = i + exit + end if + end do + if (grd < 0) then + write(errormsg, '(a,i0,2a)') 'grid, ',tape(t)%hlist(fld)%field%decomp_type,', not found for ',trim(fname_tmp) + call endrun('H_DEFINE: '//errormsg) + end if + num_hdims = header_info(grd)%num_hdims() + do i = 1, num_hdims + nacsdims(i) = header_info(grd)%get_hdimid(i) + end do + end if ! is_satfile + + fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name) + ! For restart history files, we need to save accumulation counts + fname_tmp = trim(fname_tmp)//'_nacs' + if (.not. associated(tape(t)%hlist(fld)%nacs_varid)) then + allocate(tape(t)%hlist(fld)%nacs_varid) + end if + if (size(tape(t)%hlist(fld)%nacs, 1) > 1) then + call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_int, & + nacsdims(1:num_hdims), tape(t)%hlist(fld)%nacs_varid) + else + ! Save just one value representing all chunks + call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_int, & + tape(t)%hlist(fld)%nacs_varid) + end if + + end do ! Loop over fields + end if ! deallocate(mdimids) ret = pio_enddef(tape(t)%Files(f)) diff --git a/src/control/cam_snapshot_common.F90 b/src/control/cam_snapshot_common.F90 index 81e8694006..193092a5cc 100644 --- a/src/control/cam_snapshot_common.F90 +++ b/src/control/cam_snapshot_common.F90 @@ -48,7 +48,7 @@ module cam_snapshot_common ! This is the number of pbuf fields in the CAM code that are declared with the fieldname as opposed to being data driven. -integer, parameter :: npbuf_all = 327 +integer, parameter :: npbuf_all = 314 type snapshot_type character(len=40) :: ddt_string @@ -1240,17 +1240,6 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'AurIPRateSum ','unset ',& 'awk_PBL ','unset ',& 'bprod ','unset ',& - 'cam3_bcphi ','unset ',& - 'cam3_bcpho ','unset ',& - 'cam3_dust1 ','unset ',& - 'cam3_dust2 ','unset ',& - 'cam3_dust3 ','unset ',& - 'cam3_dust4 ','unset ',& - 'cam3_ocphi ','unset ',& - 'cam3_ocpho ','unset ',& - 'cam3_ssam ','unset ',& - 'cam3_sscm ','unset ',& - 'cam3_sul ','unset ',& 'CC_ni ','unset ',& 'CC_nl ','unset ',& 'CC_qi ','unset ',& @@ -1325,9 +1314,7 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'delta_thl_PBL ','unset ',& 'delta_tr_PBL ','unset ',& 'delta_u_PBL ','unset ',& - 'delta_v_PBL ','unset '/) , (/2,100/)) - - pbuf_all(1:2,101:200) = reshape ( (/ & + 'delta_v_PBL ','unset ',& 'DES ','unset ',& 'DGNUM ','unset ',& 'DGNUMWET ','unset ',& @@ -1338,7 +1325,9 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'DP_CLDICE ','unset ',& 'DP_CLDLIQ ','unset ',& 'DP_FLXPRC ','unset ',& - 'DP_FLXSNW ','unset ',& + 'DP_FLXSNW ','unset ' /), (/2,100/)) + + pbuf_all(1:2,101:200) = reshape ( (/ & 'DP_FRAC ','unset ',& 'dragblj ','1/s ',& 'DRYMASS ','unset ',& @@ -1427,9 +1416,7 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'QCWAT ','unset ',& 'QFLX ','kg/m2/s ',& 'QFLX_RES ','unset ',& - 'QINI ','unset ' /), (/2,100/)) - - pbuf_all(1:2,201:300) = reshape ( (/ & + 'QINI ','unset ',& 'qir_det ','kg/kg ',& 'QIST ','unset ',& 'qlr_det ','kg/kg ',& @@ -1440,7 +1427,9 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'QRL ','K/s ',& 'qrlin ','unset ',& 'QRS ','K/s ',& - 'qrsin ','unset ',& + 'qrsin ','unset ' /), (/2,100/)) + + pbuf_all(1:2,201:300) = reshape ( (/ & 'QSATFAC ','- ',& 'QSNOW ','kg/kg ',& 'QTeAur ','unset ',& @@ -1481,7 +1470,6 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'SH_FLXSNW ','unset ',& 'SH_FRAC ','unset ',& 'shfrc ','unset ',& - 'smaw ','unset ',& 'SNOW_DP ','unset ',& 'SNOW_PCW ','unset ',& 'SNOW_SED ','unset ',& @@ -1523,15 +1511,12 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'TTEND_DP ','unset ',& 'TTEND_SH ','unset ',& 'T_TTEND ','unset ',& - 'turbtype ','unset ',& "UI ",'m/s ',& 'UM ','unset ',& 'UP2_nadv ','unset ',& 'UPWP ','m^2/s^2 ',& 'UZM ','M/S ',& - 'VI ','m/s ' /), (/2,100/)) - - pbuf_all(1:2,301:npbuf_all) = reshape ( (/ & + 'VI ','m/s ',& 'VM ','m/s ',& 'VOLC_MMR ','unset ',& 'VOLC_RAD_GEOM ','unset ',& @@ -1544,7 +1529,9 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'wprtp_mc_zt ','unset ',& 'WPRTP_nadv ','unset ',& 'wpthlp_mc_zt ','unset ',& - 'WPTHLP_nadv ','unset ',& + 'WPTHLP_nadv ','unset ' /), (/2,100/)) + + pbuf_all(1:2,301:npbuf_all) = reshape ( (/ & 'WPTHVP ','unset ',& 'WSEDL ','unset ',& 'wstarPBL ','unset ',& @@ -1558,7 +1545,7 @@ subroutine fill_pbuf_info(pbuf_info, pbuf, const_cname) 'ZM_MAXG ','unset ',& 'ZM_MD ','unset ',& 'ZM_MU ','unset ',& - 'ZTODT ','unset ' /), (/2,27/)) + 'ZTODT ','unset ' /), (/2,14/)) ! Fields which are added with pbuf_add_field calls, but are data driven. These are not ! included in the above list. This means that these fields will not have proper units diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 6d5a6e1058..915664cdb9 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -41,8 +41,6 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use phys_control, only: phys_ctl_readnl use wv_saturation, only: wv_sat_readnl use ref_pres, only: ref_pres_readnl - use cam3_aero_data, only: cam3_aero_data_readnl - use cam3_ozone_data, only: cam3_ozone_data_readnl use dadadj_cam, only: dadadj_readnl use macrop_driver, only: macrop_driver_readnl use microp_driver, only: microp_driver_readnl @@ -143,8 +141,6 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) call phys_ctl_readnl(nlfilename) call wv_sat_readnl(nlfilename) call ref_pres_readnl(nlfilename) - call cam3_aero_data_readnl(nlfilename) - call cam3_ozone_data_readnl(nlfilename) call dadadj_readnl(nlfilename) call macrop_driver_readnl(nlfilename) call microp_driver_readnl(nlfilename) diff --git a/src/dynamics/fv/cd_core.F90 b/src/dynamics/fv/cd_core.F90 index f7f64e6512..ad5e35aab8 100644 --- a/src/dynamics/fv/cd_core.F90 +++ b/src/dynamics/fv/cd_core.F90 @@ -251,7 +251,6 @@ subroutine cd_core(grid, nx, u, v, pt, & ! with coefficient del2coef (default 3E5) ! ! - ldiv2: 2nd-order divergence damping everywhere and increasing in top layers - ! (default cam3.5 setting) ! ! - ldiv4: 4th-order divergence damping everywhere and increasing in top layers ! @@ -530,7 +529,6 @@ subroutine cd_core(grid, nx, u, v, pt, & if (div24del2flag == 2) then - ! cam3.5 default damping setting ldiv2 = .true. ldiv4 = .false. ldel2 = .false. @@ -608,7 +606,7 @@ subroutine cd_core(grid, nx, u, v, pt, & !*********************************************** ! - ! cam3 default second-order divergence damping + ! second-order divergence damping ! !*********************************************** press = D0_5 * ( grid%ak(k)+grid%ak(k+1) + & diff --git a/src/dynamics/fv/dynamics_vars.F90 b/src/dynamics/fv/dynamics_vars.F90 index 97cbfb7d34..73f8c1e26b 100644 --- a/src/dynamics/fv/dynamics_vars.F90 +++ b/src/dynamics/fv/dynamics_vars.F90 @@ -927,7 +927,6 @@ subroutine grid_vars_init(pi, ae, om, dt, fft_flt, & grid%cosp, grid%cose, ycrit) !for filtering of u and v in div4 damping - !(needs larger halo than cam3.5 code) call pft_cf(im, jm, js2gs, jn2gd, jn1gs, & grid%scdiv4, grid%sediv4, grid%dcdiv4, grid%dediv4, & grid%cosp, grid%cose, ycrit) diff --git a/src/dynamics/se/dycore/interpolate_mod.F90 b/src/dynamics/se/dycore/interpolate_mod.F90 index 65e1e26c9b..55093dad73 100644 --- a/src/dynamics/se/dycore/interpolate_mod.F90 +++ b/src/dynamics/se/dycore/interpolate_mod.F90 @@ -1625,8 +1625,8 @@ subroutine interpolate_vector2d(interpdata,elem,fld_cube,npts,fld,input_coords, if (npts==np) then interp => interp_p - else if (npts==np) then - call endrun('interpolate_vector2d: Error in interpolate_vector(): input must be on velocity grid') + else + call endrun('interpolate_vector2d: Error in interpolate_vector(): input must be on GLL grid') endif @@ -1715,8 +1715,8 @@ subroutine interpolate_vector3d(interpdata,elem,fld_cube,npts,nlev,fld,input_coo if (npts==np) then interp => interp_p - else if (npts==np) then - call endrun('interpolate_vector3d: Error in interpolate_vector(): input must be on velocity grid') + else + call endrun('interpolate_vector3d: Error in interpolate_vector(): input must be on GLL grid') endif diff --git a/src/physics/cam/cam3_aero_data.F90 b/src/physics/cam/cam3_aero_data.F90 deleted file mode 100644 index bb32e36b8a..0000000000 --- a/src/physics/cam/cam3_aero_data.F90 +++ /dev/null @@ -1,1021 +0,0 @@ -module cam3_aero_data -!----------------------------------------------------------------------- -! -! Purposes: -! read, store, interpolate, and return fields -! of aerosols to CAM. The initialization -! file (mass.nc) is assumed to be a monthly climatology -! of aerosols from MATCH (on a sigma pressure -! coordinate system). -! also provide a "background" aerosol field to correct -! for any deficiencies in the physical parameterizations -! This fields is a "tuning" parameter. -! Public methods: -! (1) - initialization -! read aerosol masses from external file -! also pressure coordinates -! convert from monthly average values to mid-month values -! (2) - interpolation (time and vertical) -! interpolate onto pressure levels of CAM -! interpolate to time step of CAM -! return mass of aerosols -! -!----------------------------------------------------------------------- - - use shr_kind_mod, only: r8 => shr_kind_r8 - use shr_scam_mod, only: shr_scam_GetCloseLatLon - use spmd_utils, only: masterproc - use ppgrid, only: pcols, pver, pverp, begchunk, endchunk - use phys_grid, only: get_ncols_p, scatter_field_to_chunk - use time_manager, only: get_curr_calday - use infnan, only: nan, assignment(=) - use cam_abortutils, only: endrun - use scamMod, only: scmlon,scmlat,single_column - use error_messages, only: handle_ncerr - use physics_types, only: physics_state - use boundarydata, only: boundarydata_init, boundarydata_type - use perf_mod, only: t_startf, t_stopf - use cam_logfile, only: iulog - use netcdf - - implicit none - private - save - - public :: & - cam3_aero_data_readnl, & ! read namelist - cam3_aero_data_register, & ! register these aerosols with pbuf2d - cam3_aero_data_init, & ! read from file, interpolate onto horiz grid - cam3_aero_data_timestep_init ! update data-aerosols to this timestep - - ! namelist variables - logical, public :: cam3_aero_data_on = .false. - character(len=256) :: bndtvaer = 'bndtvaer' ! full pathname for time-variant aerosol mass climatology dataset - - ! naer is number of species in climatology - integer, parameter :: naer = 11 - - real(r8), parameter :: wgt_sscm = 6.0_r8 / 7.0_r8 ! Fraction of total seasalt mass in coarse mode - - ! indices to aerosol array (species portion) - integer, parameter :: & - idxSUL = 1, & - idxSSLTA = 2, & ! accumulation mode - idxSSLTC = 3, & ! coarse mode - idxOCPHO = 8, & - idxBCPHO = 9, & - idxOCPHI = 10, & - idxBCPHI = 11 - - ! indices to sections of array that represent - ! groups of aerosols - integer, parameter :: & - idxSSLTfirst = 2, numSSLT = 2, & - idxDUSTfirst = 4, & - numDUST = 4, & - idxCARBONfirst = 8, & - numCARBON = 4 - - ! names of aerosols are they are represented in - ! the climatology file. - ! Appended '_V' indicates field has been vertically summed. - character(len=8), parameter :: aerosol_name(naer) = & - (/"MSUL_V "& - ,"MSSLTA_V"& - ,"MSSLTC_V"& - ,"MDUST1_V"& - ,"MDUST2_V"& - ,"MDUST3_V"& - ,"MDUST4_V"& - ,"MOCPHO_V"& - ,"MBCPHO_V"& - ,"MOCPHI_V"& - ,"MBCPHI_V"/) - - ! number of different "groups" of aerosols - integer, parameter :: num_aer_groups=4 - - ! which group does each bin belong to? - integer, dimension(naer), parameter :: & - group =(/1,2,2,3,3,3,3,4,4,4,4/) - - ! name of each group - character(len=10), dimension(num_aer_groups), parameter :: & - aerosol_names = (/'sul ','sslt ','dust ','car '/) - - ! this boundarydata_type is used for datasets in the ncols format only. - type(boundarydata_type) :: aerosol_datan - - integer :: aernid = -1 ! netcdf id for aerosol file (init to invalid) - integer :: species_id(naer) = -1 ! netcdf_id of each aerosol species (init to invalid) - integer :: Mpsid ! netcdf id for MATCH PS - integer :: nm = 1 ! index to prv month in array. init to 1 and toggle between 1 and 2 - integer :: np = 2 ! index to nxt month in array. init to 2 and toggle between 1 and 2 - integer :: mo_nxt = huge(1) ! index to nxt month in file - - real(r8) :: cdaym ! calendar day of prv month - real(r8) :: cdayp ! calendar day of next month - - ! aerosol mass - real(r8), allocatable :: aer_mass(:, :, :, :) - - ! Days into year for mid month date - ! This variable is dumb, the dates are in the dataset to be read in but they are - ! slightly different than this so getting rid of it causes a change which - ! exceeds roundoff. - real(r8) :: Mid(12) = (/16.5_r8, 46.0_r8, 75.5_r8, 106.0_r8, 136.5_r8, 167.0_r8, & - 197.5_r8, 228.5_r8, 259.0_r8, 289.5_r8, 320.0_r8, 350.5_r8 /) - - ! values read from file and temporary values used for interpolation - ! - ! aerosolc is: - ! Cumulative Mass at midpoint of each month - ! on CAM's horizontal grid (col) - ! on MATCH's levels (lev) - ! aerosolc - integer, parameter :: paerlev = 28 ! number of levels for aerosol fields (MUST = naerlev) - integer :: naerlev ! size of level dimension in MATCH data - integer :: naerlon - integer :: naerlat - real(r8), pointer :: M_hybi(:) ! MATCH hybi - real(r8), pointer :: M_ps(:,:) ! surface pressure from MATCH file - real(r8), pointer :: aerosolc(:,:,:,:,:) ! Aerosol cumulative mass from MATCH - real(r8), pointer :: M_ps_cam_col(:,:,:) ! PS from MATCH on Cam Columns - - ! indices for fields in the physics buffer - integer :: cam3_sul_idx, cam3_ssam_idx, cam3_sscm_idx, & - cam3_dust1_idx, cam3_dust2_idx, cam3_dust3_idx, cam3_dust4_idx,& - cam3_ocpho_idx, cam3_bcpho_idx, cam3_ocphi_idx, cam3_bcphi_idx - -!================================================================================================ -contains -!================================================================================================ - -subroutine cam3_aero_data_readnl(nlfile) - - use namelist_utils, only: find_group_name - use units, only: getunit, freeunit - use mpishorthand - - character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input - - ! Local variables - integer :: unitn, ierr - character(len=*), parameter :: subname = 'cam3_aero_data_readnl' - - namelist /cam3_aero_data_nl/ cam3_aero_data_on, bndtvaer - !----------------------------------------------------------------------------- - - if (masterproc) then - unitn = getunit() - open( unitn, file=trim(nlfile), status='old' ) - call find_group_name(unitn, 'cam3_aero_data_nl', status=ierr) - if (ierr == 0) then - read(unitn, cam3_aero_data_nl, iostat=ierr) - if (ierr /= 0) then - call endrun(subname // ':: ERROR reading namelist') - end if - end if - close(unitn) - call freeunit(unitn) - end if - -#ifdef SPMD - ! Broadcast namelist variables - call mpibcast(cam3_aero_data_on, 1, mpilog, 0, mpicom) - call mpibcast(bndtvaer, len(bndtvaer), mpichar, 0, mpicom) -#endif - - ! Prevent using these before they are set. - cdaym = nan - cdayp = nan - -end subroutine cam3_aero_data_readnl - -!================================================================================================ - -subroutine cam3_aero_data_register - - ! register old prescribed aerosols with physics buffer - - use physics_buffer, only: pbuf_add_field, dtype_r8 - - call pbuf_add_field('cam3_sul', 'physpkg',dtype_r8,(/pcols,pver/),cam3_sul_idx) - call pbuf_add_field('cam3_ssam', 'physpkg',dtype_r8,(/pcols,pver/),cam3_ssam_idx) - call pbuf_add_field('cam3_sscm', 'physpkg',dtype_r8,(/pcols,pver/),cam3_sscm_idx) - call pbuf_add_field('cam3_dust1','physpkg',dtype_r8,(/pcols,pver/),cam3_dust1_idx) - call pbuf_add_field('cam3_dust2','physpkg',dtype_r8,(/pcols,pver/),cam3_dust2_idx) - call pbuf_add_field('cam3_dust3','physpkg',dtype_r8,(/pcols,pver/),cam3_dust3_idx) - call pbuf_add_field('cam3_dust4','physpkg',dtype_r8,(/pcols,pver/),cam3_dust4_idx) - call pbuf_add_field('cam3_ocpho','physpkg',dtype_r8,(/pcols,pver/),cam3_ocpho_idx) - call pbuf_add_field('cam3_bcpho','physpkg',dtype_r8,(/pcols,pver/),cam3_bcpho_idx) - call pbuf_add_field('cam3_ocphi','physpkg',dtype_r8,(/pcols,pver/),cam3_ocphi_idx) - call pbuf_add_field('cam3_bcphi','physpkg',dtype_r8,(/pcols,pver/),cam3_bcphi_idx) - -end subroutine cam3_aero_data_register - -!================================================================================================ - -subroutine cam3_aero_data_init(phys_state) -!------------------------------------------------------------------ -! Reads in: -! file from which to read aerosol Masses on CAM grid. Currently -! assumed to be MATCH ncep runs, averaged by month. -! NOTE (Data have been externally interpolated onto CAM grid -! and backsolved to provide Mid-month values) -! -! Populates: -! module variables: -! aerosolc(pcols,paerlev+1,begchunk:endchunk,naer,2)) -! aerosolc( column_index -! , level_index (match levels) -! , chunk_index -! , species_index -! , month = 1:2 ) -! M_hybi(level_index = Lev_MATCH) = pressure at mid-level. -! M_ps_cam_col(column,chunk,month) ! PS from MATCH on Cam Columns -! -! Method: -! read data from file -! allocate memory for storage of aerosol data on CAM horizontal grid -! distribute data to remote nodes -! populates the module variables -! -!------------------------------------------------------------------ - use ioFileMod, only: getfil - -#if ( defined SPMD ) - use mpishorthand -#endif - type(physics_state), intent(in) :: phys_state(begchunk:endchunk) - -! local variables - - integer :: naerlev - - integer dateid ! netcdf id for date variable - integer secid ! netcdf id for seconds variable - integer londimid ! netcdf id for longitude dimension - integer latdimid ! netcdf id for latitude dimension - integer levdimid ! netcdf id for level dimension - - integer timesiz ! number of time samples (=12) in netcdf file - integer latid ! netcdf id for latitude variable - integer Mhybiid ! netcdf id for MATCH hybi - integer timeid ! netcdf id for time variable - integer dimids(nf90_max_var_dims) ! variable shape - integer :: start(4) ! start vector for netcdf calls - integer :: kount(4) ! count vector for netcdf calls - integer mo ! month index - integer m ! constituent index - integer :: n ! loop index - integer :: i,j,k ! spatial indices - integer :: date_aer(12) ! Date on aerosol dataset (YYYYMMDD) - integer :: attnum ! attribute number - integer :: ierr ! netcdf return code - real(r8) :: coldata(paerlev) ! aerosol field read in from dataset - integer :: ret - integer mo_prv ! index to previous month - integer latidx,lonidx - - character(len=8) :: aname ! temporary aerosol name - character(len=8) :: tmp_aero_name(naer) ! name for input to boundary data - - character(len=256) :: locfn ! netcdf local filename to open -! -! aerosol_data will be read in from the aerosol boundary dataset, then scattered to chunks -! after filling in the bottom level with zeros -! - real(r8), allocatable :: aerosol_data(:,:,:) ! aerosol field read in from dataset - real(r8), allocatable :: aerosol_field(:,:,:) ! (plon,paerlev+1,plat) aerosol field to be scattered - real(r8) :: caldayloc ! calendar day of current timestep - real(r8) :: closelat,closelon - - character(len=*), parameter :: subname = 'cam3_aero_data_init' - !------------------------------------------------------------------ - - call t_startf(subname) - - allocate (aer_mass(pcols, pver, naer, begchunk:endchunk) ) - - ! set new aerosol names because input file has 1 seasalt bin - do m = 1, naer - tmp_aero_name(m)=aerosol_name(m) - if (aerosol_name(m)=='MSSLTA_V') tmp_aero_name(m) = 'MSSLT_V' - if (aerosol_name(m)=='MSSLTC_V') tmp_aero_name(m) = 'MSSLT_V' - end do - - allocate (aerosolc(pcols,paerlev+1,begchunk:endchunk,naer,2)) - aerosolc(:,:,:,:,:) = 0._r8 - - caldayloc = get_curr_calday () - - if (caldayloc < Mid(1)) then - mo_prv = 12 - mo_nxt = 1 - else if (caldayloc >= Mid(12)) then - mo_prv = 12 - mo_nxt = 1 - else - do i = 2 , 12 - if (caldayloc < Mid(i)) then - mo_prv = i-1 - mo_nxt = i - exit - end if - end do - end if - - ! Set initial calendar day values - cdaym = Mid(mo_prv) - cdayp = Mid(mo_nxt) - - if (masterproc) & - write(iulog,*) subname//': CAM3 prescribed aerosol dataset is: ', trim(bndtvaer) - - call getfil (bndtvaer, locfn, 0) - - call handle_ncerr( nf90_open (locfn, 0, aernid),& - subname, __LINE__) - - if (single_column) & - call shr_scam_GetCloseLatLon(aernid,scmlat,scmlon,closelat,closelon,latidx,lonidx) - - ! Check to see if this dataset is in ncol format. - aerosol_datan%isncol=.false. - ierr = nf90_inq_dimid( aernid, 'ncol', londimid ) - if ( ierr==NF90_NOERR ) then - - aerosol_datan%isncol=.true. - call handle_ncerr(nf90_close(aernid),subname, __LINE__) - - call boundarydata_init(bndtvaer, phys_state, tmp_aero_name, naer, & - aerosol_datan, 3) - - aerosolc(:,1:paerlev,:,:,:)=aerosol_datan%fields - - M_ps_cam_col=>aerosol_datan%ps - M_hybi=>aerosol_datan%hybi - - else - - ! Allocate memory for dynamic arrays local to this module - allocate (M_ps_cam_col(pcols,begchunk:endchunk,2)) - allocate (M_hybi(paerlev+1)) - ! TBH: HACK to avoid use of uninitialized values when ncols < pcols - M_ps_cam_col(:,:,:) = 0._r8 - - if (masterproc) then - - ! First ensure dataset is CAM-ready - - call handle_ncerr(nf90_inquire_attribute (aernid, nf90_global, 'cam-ready', attnum=attnum),& - subname//': interpaerosols needs to be run to create a cam-ready aerosol dataset') - - ! Get and check dimension info - - call handle_ncerr( nf90_inq_dimid( aernid, 'lon', londimid ),& - subname, __LINE__) - call handle_ncerr( nf90_inq_dimid( aernid, 'lev', levdimid ),& - subname, __LINE__) - call handle_ncerr( nf90_inq_dimid( aernid, 'time', timeid ),& - subname, __LINE__) - call handle_ncerr( nf90_inq_dimid( aernid, 'lat', latdimid ),& - subname, __LINE__) - call handle_ncerr( nf90_inquire_dimension( aernid, londimid, len=naerlon ),& - subname, __LINE__) - call handle_ncerr( nf90_inquire_dimension( aernid, levdimid, len=naerlev ),& - subname, __LINE__) - call handle_ncerr( nf90_inquire_dimension( aernid, latdimid, len=naerlat ),& - subname, __LINE__) - call handle_ncerr( nf90_inquire_dimension( aernid, timeid, len=timesiz ),& - subname, __LINE__) - - call handle_ncerr( nf90_inq_varid( aernid, 'date', dateid ),& - subname, __LINE__) - call handle_ncerr( nf90_inq_varid( aernid, 'datesec', secid ),& - subname, __LINE__) - - do m = 1, naer - aname=aerosol_name(m) - ! rename because file has only one seasalt field - if (aname=='MSSLTA_V') aname = 'MSSLT_V' - if (aname=='MSSLTC_V') aname = 'MSSLT_V' - call handle_ncerr( nf90_inq_varid( aernid, TRIM(aname), species_id(m)), & - subname, __LINE__) - end do - - call handle_ncerr( nf90_inq_varid( aernid, 'lat', latid ),& - subname, __LINE__) - - ! quick sanity check on one field - call handle_ncerr( nf90_inquire_variable (aernid, species_id(1), dimids=dimids),& - subname, __LINE__) - - if ( (dimids(4) /= timeid) .or. & - (dimids(3) /= levdimid) .or. & - (dimids(2) /= latdimid) .or. & - (dimids(1) /= londimid) ) then - write(iulog,*) subname//': Data must be ordered time, lev, lat, lon' - write(iulog,*) 'data are ordered as', dimids(4), dimids(3), dimids(2), dimids(1) - write(iulog,*) 'data should be ordered as', timeid, levdimid, latdimid, londimid - call endrun () - end if - - ! use hybi,PS from MATCH - call handle_ncerr( nf90_inq_varid( aernid, 'hybi', Mhybiid ),& - subname, __LINE__) - call handle_ncerr( nf90_inq_varid( aernid, 'PS', Mpsid ),& - subname, __LINE__) - - ! check dimension order for MATCH's surface pressure - call handle_ncerr( nf90_inquire_variable (aernid, Mpsid, dimids=dimids),& - subname, __LINE__) - if ( (dimids(3) /= timeid) .or. & - (dimids(2) /= latdimid) .or. & - (dimids(1) /= londimid) ) then - write(iulog,*) subname//': Pressure must be ordered time, lat, lon' - write(iulog,*) 'data are ordered as', dimids(3), dimids(2), dimids(1) - write(iulog,*) 'data should be ordered as', timeid, levdimid, latdimid, londimid - call endrun () - end if - - ! read in hybi from MATCH - call handle_ncerr( nf90_get_var (aernid, Mhybiid, M_hybi),& - subname, __LINE__) - - ! Retrieve date and sec variables. - call handle_ncerr( nf90_get_var (aernid, dateid, date_aer),& - subname, __LINE__) - if (timesiz < 12) then - write(iulog,*) subname//': When cycling aerosols, dataset must have 12 consecutive ', & - 'months of data starting with Jan' - write(iulog,*) 'Current dataset has only ',timesiz,' months' - call endrun () - end if - do mo = 1,12 - if (mod(date_aer(mo),10000)/100 /= mo) then - write(iulog,*) subname//': When cycling aerosols, dataset must have 12 consecutive ', & - 'months of data starting with Jan' - write(iulog,*)'Month ',mo,' of dataset says date=',date_aer(mo) - call endrun () - end if - end do - if (single_column) then - naerlat=1 - naerlon=1 - endif - kount(:) = (/naerlon,naerlat,paerlev,1/) - end if ! masterproc - - ! broadcast hybi to nodes - -#if ( defined SPMD ) - call mpibcast (M_hybi, paerlev+1, mpir8, 0, mpicom) - call mpibcast (kount, 3, mpiint, 0, mpicom) - naerlon = kount(1) - naerlat = kount(2) -#endif - allocate(aerosol_field(kount(1),kount(3)+1,kount(2))) - allocate(M_ps(kount(1),kount(2))) - if (masterproc) allocate(aerosol_data(kount(1),kount(2),kount(3))) - - ! Retrieve Aerosol Masses (kg/m^2 in each layer), transpose to model order (lon,lev,lat), - ! then scatter to slaves. - if (nm /= 1 .or. np /= 2) call endrun (subname//': bad nm or np value') - do n=nm,np - if (n == 1) then - mo = mo_prv - else - mo = mo_nxt - end if - - do m=1,naer - if (masterproc) then - if (single_column) then - start(:) = (/lonidx,latidx,1,mo/) - else - start(:) = (/1,1,1,mo/) - endif - kount(:) = (/naerlon,naerlat,paerlev,1/) - - call handle_ncerr( nf90_get_var (aernid, species_id(m),aerosol_data, start, kount),& - subname, __LINE__) - do j=1,naerlat - do k=1,paerlev - aerosol_field(:,k,j) = aerosol_data(:,j,k) - end do - aerosol_field(:,paerlev+1,j) = 0._r8 ! value at bottom - end do - - end if - call scatter_field_to_chunk (1, paerlev+1, 1, naerlon, aerosol_field, & - aerosolc(:,:,:,m,n)) - end do - - ! Retrieve PS from Match - - if (masterproc) then - if (single_column) then - start(:) = (/lonidx,latidx,mo,-1/) - else - start(:) = (/1,1,mo,-1/) - endif - kount(:) = (/naerlon,naerlat,1,-1/) - call handle_ncerr( nf90_get_var(aernid, Mpsid, M_ps,start,kount),& - subname, __LINE__) - end if - call scatter_field_to_chunk (1, 1, 1, naerlon, M_ps(:,:), M_ps_cam_col(:,:,n)) - end do ! n=nm,np (=1,2) - - if(masterproc) deallocate(aerosol_data) - deallocate(aerosol_field) - - end if ! Check to see if this dataset is in ncol format. - - call t_stopf(subname) - -end subroutine cam3_aero_data_init - -!================================================================================================ - -subroutine cam3_aero_data_timestep_init(pbuf2d, phys_state) -!------------------------------------------------------------------ -! -! Input: -! time at which aerosol masses are needed (get_curr_calday()) -! chunk index -! CAM's vertical grid (pint) -! -! Output: -! values for Aerosol Mass at time specified by get_curr_calday -! on vertical grid specified by pint (aer_mass) :: aerosol at time t -! -! Method: -! first determine which indexs of aerosols are the bounding data sets -! interpolate both onto vertical grid aerm(),aerp(). -! from those two, interpolate in time. -! -!------------------------------------------------------------------ - - use interpolate_data, only: get_timeinterp_factors - - use physics_buffer, only: physics_buffer_desc, dtype_r8, pbuf_set_field, pbuf_get_chunk - use cam_logfile, only: iulog - use ppgrid, only: begchunk,endchunk - use physconst, only: gravit - -! -! aerosol fields interpolated to current time step -! on pressure levels of this time step. -! these should be made read-only for other modules -! Is allocation done correctly here? -! - - type(physics_buffer_desc), pointer :: pbuf2d(:,:) - type(physics_state), intent(in), dimension(begchunk:endchunk) :: phys_state - -! -! Local workspace -! - type(physics_buffer_desc), pointer :: phys_buffer_chunk(:) - real(r8) :: pint(pcols,pverp) ! interface pres. - integer :: c ! chunk index - real(r8) caldayloc ! calendar day of current timestep - real(r8) fact1, fact2 ! time interpolation factors - - integer i, k, j ! spatial indices - integer m ! constituent index - integer lats(pcols),lons(pcols) ! latitude and longitudes of column - integer ncol ! number of columns - integer lchnk ! chunk index - - real(r8) speciesmin(naer) ! minimal value for each species -! -! values before current time step "the minus month" -! aerosolm(pcols,pver) is value of preceeding month's aerosol masses -! aerosolp(pcols,pver) is value of next month's aerosol masses -! (think minus and plus or values to left and right of point to be interpolated) -! - real(r8) aerosolm(pcols,pver,naer,begchunk:endchunk) ! aerosol mass from MATCH in column,level at previous (minus) month -! -! values beyond (or at) current time step "the plus month" -! - real(r8) aerosolp(pcols,pver,naer,begchunk:endchunk) ! aerosol mass from MATCH in column,level at next (plus) month - real(r8) :: mass_to_mmr(pcols,pver) - - character(len=*), parameter :: subname = 'cam3_aero_data_timestep_init' - - logical error_found - !------------------------------------------------------------------ - - call aerint(phys_state) - - caldayloc = get_curr_calday () - - ! Determine time interpolation factors. 1st arg says we are cycling 1 year of data - call get_timeinterp_factors (.true., mo_nxt, cdaym, cdayp, caldayloc, & - fact1, fact2, 'GET_AEROSOL:') - - ! interpolate (prv and nxt month) bounding datasets onto cam vertical grid. - ! compute mass mixing ratios on CAMS's pressure coordinate - ! for both the "minus" and "plus" months - ! - ! This loop over chunk could probably be removed by working with the whole - ! begchunk:endchunk group at once. It would require a slight generalization - ! in vert_interpolate. - do c = begchunk,endchunk - - lchnk = phys_state(c)%lchnk - pint = phys_state(c)%pint - ncol = get_ncols_p(c) - - call vert_interpolate (M_ps_cam_col(:,c,nm), pint, nm, aerosolm(:,:,:,c), ncol, c) - call vert_interpolate (M_ps_cam_col(:,c,np), pint, np, aerosolp(:,:,:,c), ncol, c) - - ! Time interpolate. - do m=1,naer - do k=1,pver - do i=1,ncol - aer_mass(i,k,m,c) = aerosolm(i,k,m,c)*fact1 + aerosolp(i,k,m,c)*fact2 - end do - end do - ! Partition seasalt aerosol mass - if (m .eq. idxSSLTA) then - aer_mass(:ncol,:,m,c) = (1._r8-wgt_sscm)*aer_mass(:ncol,:,m,c) ! fraction of seasalt mass in accumulation mode - elseif (m .eq. idxSSLTC) then - aer_mass(:ncol,:,m,c) = wgt_sscm*aer_mass(:ncol,:,m,c) ! fraction of seasalt mass in coarse mode - endif - end do - - ! exit if mass is negative (we have previously set - ! cumulative mass to be a decreasing function.) - speciesmin(:) = 0._r8 ! speciesmin(m) = 0 is minimum mass for each species - - error_found = .false. - do m=1,naer - do k=1,pver - do i=1,ncol - if (aer_mass(i, k, m,c) < speciesmin(m)) error_found = .true. - end do - end do - end do - if (error_found) then - do m=1,naer - do k=1,pver - do i=1,ncol - if (aer_mass(i, k, m,c) < speciesmin(m)) then - write(iulog,*) subname//': negative mass mixing ratio, exiting' - write(iulog,*) 'm, column, pver',m, i, k ,aer_mass(i, k, m,c) - call endrun () - end if - end do - end do - end do - end if - do k = 1, pver - mass_to_mmr(1:ncol,k) = gravit/(pint(1:ncol,k+1)-pint(1:ncol,k)) - enddo - - phys_buffer_chunk => pbuf_get_chunk(pbuf2d, lchnk) - - call pbuf_set_field(phys_buffer_chunk, cam3_sul_idx, aer_mass(1:ncol,:, idxSUL,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_ssam_idx, aer_mass(1:ncol,:, idxSSLTA,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_sscm_idx, aer_mass(1:ncol,:, idxSSLTC,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_dust1_idx, aer_mass(1:ncol,:, idxDUSTfirst,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_dust2_idx, aer_mass(1:ncol,:,idxDUSTfirst+1,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_dust3_idx, aer_mass(1:ncol,:,idxDUSTfirst+2,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_dust4_idx, aer_mass(1:ncol,:,idxDUSTfirst+3,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_ocpho_idx, aer_mass(1:ncol,:, idxOCPHO,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_bcpho_idx, aer_mass(1:ncol,:, idxBCPHO,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_ocphi_idx, aer_mass(1:ncol,:, idxOCPHI,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - call pbuf_set_field(phys_buffer_chunk, cam3_bcphi_idx, aer_mass(1:ncol,:, idxBCPHI,c)*mass_to_mmr(:ncol,:), & - start=(/1,1/), kount=(/ncol,pver/)) - - enddo ! c = begchunk:endchunk - -end subroutine cam3_aero_data_timestep_init - -!================================================================================================ - -subroutine vert_interpolate (Match_ps, pint, n, aerosol_mass, ncol, c) -!-------------------------------------------------------------------- -! Input: match surface pressure, cam interface pressure, -! month index, number of columns, chunk index -! -! Output: Aerosol mass mixing ratio (aerosol_mass) -! -! Method: -! interpolate column mass (cumulative) from match onto -! cam's vertical grid (pressure coordinate) -! convert back to mass mixing ratio -! -!-------------------------------------------------------------------- - - real(r8), intent(out) :: aerosol_mass(pcols,pver,naer) ! aerosol mass from MATCH - real(r8), intent(in) :: Match_ps(pcols) ! surface pressure at a particular month - real(r8), intent(in) :: pint(pcols,pverp) ! interface pressure from CAM - - integer, intent(in) :: ncol,c ! chunk index and number of columns - integer, intent(in) :: n ! prv or nxt month index -! -! Local workspace -! - integer m ! index to aerosol species - integer kupper(pcols) ! last upper bound for interpolation - integer i, k, kk, kkstart, kount ! loop vars for interpolation - integer isv, ksv, msv ! loop indices to save - - logical bad ! indicates a bad point found - logical lev_interp_comp ! interpolation completed for a level - logical error_found - - real(r8) aerosol(pcols,pverp,naer) ! cumulative mass of aerosol in column beneath upper - ! interface of level in column at particular month - real(r8) dpl, dpu ! lower and upper intepolation factors - real(r8) v_coord ! vertical coordinate - real(r8) AER_diff ! temp var for difference between aerosol masses - - character(len=*), parameter :: subname = 'cam3_aero_data.vert_interpolate' - !----------------------------------------------------------------------- - - call t_startf ('vert_interpolate') -! -! Initialize index array -! - do i=1,ncol - kupper(i) = 1 - end do -! -! assign total mass to topmost level -! - aerosol(:,1,:) = aerosolc(:,1,c,:,n) -! -! At every pressure level, interpolate onto that pressure level -! - do k=2,pver -! -! Top level we need to start looking is the top level for the previous k -! for all longitude points -! - kkstart = paerlev+1 - do i=1,ncol - kkstart = min0(kkstart,kupper(i)) - end do - kount = 0 -! -! Store level indices for interpolation -! -! for the pressure interpolation should be comparing -! pint(column,lev) with M_hybi(lev)*M_ps_cam_col(month,column,chunk) -! - lev_interp_comp = .false. - do kk=kkstart,paerlev - if(.not.lev_interp_comp) then - do i=1,ncol - v_coord = pint(i,k) - if (M_hybi(kk)*Match_ps(i) .lt. v_coord .and. v_coord .le. M_hybi(kk+1)*Match_ps(i)) then - kupper(i) = kk - kount = kount + 1 - end if - end do -! -! If all indices for this level have been found, do the interpolation and -! go to the next level -! -! Interpolate in pressure. -! - if (kount.eq.ncol) then - do m=1,naer - do i=1,ncol - dpu = pint(i,k) - M_hybi(kupper(i))*Match_ps(i) - dpl = M_hybi(kupper(i)+1)*Match_ps(i) - pint(i,k) - aerosol(i,k,m) = & - (aerosolc(i,kupper(i) ,c,m,n)*dpl + & - aerosolc(i,kupper(i)+1,c,m,n)*dpu)/(dpl + dpu) - enddo !i - end do - lev_interp_comp = .true. - end if - end if - end do -! -! If we've fallen through the kk=1,levsiz-1 loop, we cannot interpolate and -! must extrapolate from the bottom or top pressure level for at least some -! of the longitude points. -! - - if(.not.lev_interp_comp) then - do m=1,naer - do i=1,ncol - if (pint(i,k) .lt. M_hybi(1)*Match_ps(i)) then - aerosol(i,k,m) = aerosolc(i,1,c,m,n) - else if (pint(i,k) .gt. M_hybi(paerlev+1)*Match_ps(i)) then - aerosol(i,k,m) = 0.0_r8 - else - dpu = pint(i,k) - M_hybi(kupper(i))*Match_ps(i) - dpl = M_hybi(kupper(i)+1)*Match_ps(i) - pint(i,k) - aerosol(i,k,m) = & - (aerosolc(i,kupper(i) ,c,m,n)*dpl + & - aerosolc(i,kupper(i)+1,c,m,n)*dpu)/(dpl + dpu) - end if - end do - end do - - if (kount.gt.ncol) then - call endrun (subname//': Bad data: non-monotonicity suspected in dependent variable') - end if - end if - end do - -! call t_startf ('vi_checks') -! -! aerosol mass beneath lowest interface (pverp) must be 0 -! - aerosol(1:ncol,pverp,:) = 0._r8 -! -! Set mass in layer to zero whenever it is less than -! 1.e-40 kg/m^2 in the layer -! - do m = 1, naer - do k = 1, pver - do i = 1, ncol - if (aerosol(i,k,m) < 1.e-40_r8) aerosol(i,k,m) = 0._r8 - end do - end do - end do -! -! Set mass in layer to zero whenever it is less than -! 10^-15 relative to column total mass -! - error_found = .false. - do m = 1, naer - do k = 1, pver - do i = 1, ncol - AER_diff = aerosol(i,k,m) - aerosol(i,k+1,m) - if( abs(AER_diff) < 1e-15_r8*aerosol(i,1,m)) then - AER_diff = 0._r8 - end if - aerosol_mass(i,k,m)= AER_diff - if (aerosol_mass(i,k,m) < 0) error_found = .true. - end do - end do - end do - if (error_found) then - do m = 1, naer - do k = 1, pver - do i = 1, ncol - if (aerosol_mass(i,k,m) < 0) then - write(iulog,*) subname//': mass < 0, m, col, lev, mass',m, i, k, aerosol_mass(i,k,m) - write(iulog,*) subname//': aerosol(k),(k+1)',aerosol(i,k,m),aerosol(i,k+1,m) - write(iulog,*) subname//': pint(k+1),(k)',pint(i,k+1),pint(i,k) - write(iulog,*)'n,c',n,c - call endrun() - end if - end do - end do - end do - end if - - call t_stopf ('vert_interpolate') - - return -end subroutine vert_interpolate - -!================================================================================================ - -subroutine aerint (phys_state) - - type(physics_state), intent(in) :: phys_state(begchunk:endchunk) - - integer :: ntmp ! used in index swapping - integer :: start(4) ! start vector for netcdf calls - integer :: kount(4) ! count vector for netcdf calls - integer :: i,j,k ! spatial indices - integer :: m ! constituent index - integer :: cols, cole - integer :: lchnk, ncol - real(r8) :: caldayloc ! calendar day of current timestep - real(r8) :: aerosol_data(naerlon,naerlat,paerlev) ! aerosol field read in from dataset - real(r8) :: aerosol_field(naerlon,paerlev+1,naerlat) ! aerosol field to be scattered - integer latidx,lonidx - real(r8) closelat,closelon - - character(len=*), parameter :: subname = 'cam3_aero_data.aerint' - !----------------------------------------------------------------------- - - if (single_column) & - call shr_scam_GetCloseLatLon(aernid,scmlat,scmlon,closelat,closelon,latidx,lonidx) - -! -! determine if need to read in next month data -! also determine time interpolation factors -! - caldayloc = get_curr_calday () -! -! If model time is past current forward timeslice, then -! masterproc reads in the next timeslice for time interpolation. Messy logic is -! for interpolation between December and January (mo_nxt == 1). Just like -! ozone_data_timestep_init, sstint. -! - if (caldayloc > cdayp .and. .not. (mo_nxt == 1 .and. caldayloc >= cdaym)) then - mo_nxt = mod(mo_nxt,12) + 1 - cdaym = cdayp - cdayp = Mid(mo_nxt) -! -! Check for valid date info -! - if (.not. (mo_nxt == 1 .or. caldayloc <= cdayp)) then - call endrun (subname//': Non-monotonicity suspected in input aerosol data') - end if - - ntmp = nm - nm = np - np = ntmp - - if(aerosol_datan%isncol) then - do lchnk=begchunk,endchunk - ncol=phys_state(lchnk)%ncol - cols=1 - cole=cols+aerosol_datan%count(cols,lchnk)-1 - do while(cole<=ncol) - start=(/aerosol_datan%start(cols,lchnk),mo_nxt,1,-1/) - kount=(/aerosol_datan%count(cols,lchnk),1,-1,-1/) - call handle_ncerr( nf90_get_var(aerosol_datan%ncid, aerosol_datan%psid , & - aerosol_datan%ps(cols:cole,lchnk,np), start(1:2), & - kount(1:2)),& - subname, __LINE__) - start(2)=1 - start(3)=mo_nxt - kount(2)=paerlev - kount(3)=1 - do m=1,naer - call handle_ncerr( nf90_get_var(aerosol_datan%ncid, aerosol_datan%dataid(m) , & - aerosol_datan%fields(cols:cole,:,lchnk,m,np), & - start(1:3), kount(1:3)),& - subname, __LINE__) - - end do - if(cols==ncol) exit - cols=cols+aerosol_datan%count(cols,lchnk) - cole=cols+aerosol_datan%count(cols,lchnk)-1 - end do - end do - aerosolc(:,1:paerlev,:,:,np)=aerosol_datan%fields(:,:,:,:,np) - else - do m=1,naer - if (masterproc) then - if (single_column) then - naerlon=1 - naerlat=1 - start(:) = (/lonidx,latidx,1,mo_nxt/) - else - start(:) = (/1,1,1,mo_nxt/) - endif - kount(:) = (/naerlon,naerlat,paerlev,1/) - call handle_ncerr( nf90_get_var (aernid, species_id(m), aerosol_data, start, kount),& - subname, __LINE__) - - do j=1,naerlat - do k=1,paerlev - aerosol_field(:,k,j) = aerosol_data(:,j,k) - end do - aerosol_field(:,paerlev+1,j) = 0._r8 ! value at bottom - end do - end if - call scatter_field_to_chunk (1, paerlev+1, 1, naerlon, aerosol_field, & - aerosolc(:,:,:,m,np)) - end do -! -! Retrieve PS from Match -! - if (masterproc) then - if (single_column) then - naerlon=1 - naerlat=1 - start(:) = (/lonidx,latidx,mo_nxt,-1/) - else - start(:) = (/1,1,mo_nxt,-1/) - endif - kount(:) = (/naerlon,naerlat,1,-1/) - call handle_ncerr( nf90_get_var (aernid, Mpsid, M_ps, start, kount),& - subname, __LINE__) - write(iulog,*) subname//': Read aerosols data for julian day', Mid(mo_nxt) - end if - call scatter_field_to_chunk (1, 1, 1, naerlon, M_ps(:,:), M_ps_cam_col(:,:,np)) - end if - end if - -end subroutine aerint - -end module cam3_aero_data diff --git a/src/physics/cam/cam3_ozone_data.F90 b/src/physics/cam/cam3_ozone_data.F90 deleted file mode 100644 index 567679fb0d..0000000000 --- a/src/physics/cam/cam3_ozone_data.F90 +++ /dev/null @@ -1,220 +0,0 @@ -module cam3_ozone_data - -!----------------------------------------------------------------------- -! Purpose: -! -! Interpolates zonal ozone datasets used by CAM3 and puts the field 'O3' into -! the physics buffer. -! -! Revision history: -! 2004-07-31 B. Eaton Assemble module from comozp.F90, oznini.F90, oznint.F90, radozn.F90 -! 2004-08-19 B. Eaton Modify ozone_data_vert_interp to return mass mixing ratio. -! 2004-08-30 B. Eaton Add ozone_data_get_cnst method. -! 2008 June B. Eaton Change name to cam3_ozone_data to support backwards compatibility -! for reading the CAM3 ozone data. Add *_readnl method so module -! reads its own namelist. Add cam3_ozone_data_on variable to -! turn the module on from the namelist. By default it's off. -!----------------------------------------------------------------------- - -use shr_kind_mod, only: r8 => shr_kind_r8 -use spmd_utils, only: masterproc -use ppgrid, only: begchunk, endchunk, pcols, pver -use cam_abortutils, only: endrun -use cam_logfile, only: iulog -use physics_types, only: physics_state -use boundarydata, only: boundarydata_type, boundarydata_init, boundarydata_update, & - boundarydata_vert_interp -use mpishorthand - -implicit none -private -save - -! Public methods -public ::& - cam3_ozone_data_readnl, &! get namelist input - cam3_ozone_data_register, &! register ozone with physics buffer - cam3_ozone_data_init, &! open dataset and spatially interpolate data bounding initial time - cam3_ozone_data_timestep_init ! interpolate to current time - -! Namelist variables -logical, public :: cam3_ozone_data_on = .false. ! switch to turn module on/off -logical :: ozncyc = .true. ! .true. => assume annual cycle ozone data -character(len=256) :: bndtvo = ' ' ! full pathname for time-variant ozone dataset - -! Local -integer :: oz_idx ! index into phys_buffer for ozone - -type(boundarydata_type) :: ozonedata -character(len=6), parameter, dimension(1) :: nc_name = (/'OZONE '/) ! constituent names - -!================================================================================================ -contains -!================================================================================================ - -subroutine cam3_ozone_data_readnl(nlfile) - - use namelist_utils, only: find_group_name - use units, only: getunit, freeunit - use mpishorthand - - character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input - - ! Local variables - integer :: unitn, ierr - character(len=*), parameter :: subname = 'cam3_ozone_data_readnl' - - namelist /cam3_ozone_data_nl/ cam3_ozone_data_on, bndtvo, ozncyc - !----------------------------------------------------------------------------- - - if (masterproc) then - unitn = getunit() - open( unitn, file=trim(nlfile), status='old' ) - call find_group_name(unitn, 'cam3_ozone_data_nl', status=ierr) - if (ierr == 0) then - read(unitn, cam3_ozone_data_nl, iostat=ierr) - if (ierr /= 0) then - call endrun(subname // ':: ERROR reading namelist') - end if - end if - close(unitn) - call freeunit(unitn) - end if - -#ifdef SPMD - ! Broadcast namelist variables - call mpibcast(cam3_ozone_data_on, 1, mpilog, 0, mpicom) - call mpibcast(bndtvo, len(bndtvo), mpichar, 0, mpicom) - call mpibcast(ozncyc, 1, mpilog, 0, mpicom) -#endif - -end subroutine cam3_ozone_data_readnl - -!================================================================================================ - -subroutine cam3_ozone_data_register() - use physics_buffer, only : pbuf_add_field, dtype_r8 - - call pbuf_add_field('O3','physpkg',dtype_r8,(/pcols,pver/),oz_idx) - -end subroutine cam3_ozone_data_register - -!================================================================================================ - -subroutine cam3_ozone_data_init(phys_state) -!----------------------------------------------------------------------- -! -! Purpose: Do initial read of time-variant ozone boundary dataset, containing -! ozone mixing ratios as a function of latitude and pressure. Read two -! consecutive months between which the current date lies. Routine -! RADOZ2 then evaluates the two path length integrals (with and without -! pressure weighting) from zero to the interfaces between the input -! levels. It also stores the contribution to the integral from each -! layer. -! -! Method: Call appropriate netcdf wrapper routines and interpolate to model grid -! -! Author: CCM Core Group -! Modified: P. Worley, August 2003, for chunking and performance optimization -! J. Edwards, Dec 2005, functionality now performed by zonalbndrydata -!----------------------------------------------------------------------- - - use cam_history, only: addfld - - type(physics_state), intent(in) :: phys_state(begchunk:endchunk) - !----------------------------------------------------------------------- - - call addfld ('O3VMR', (/ 'lev' /), 'A', 'm3/m3', 'Ozone volume mixing ratio', sampling_seq='rad_lwsw') - - - ! Initialize for one field (arg_4=1) and do not vertically interpolate (arg_6=3) - call boundarydata_init(bndtvo, phys_state, nc_name, 1, ozonedata, 3) - - if (masterproc) then - write(iulog,*)'cam3_ozone_data_init: Initializing CAM3 prescribed ozone' - write(iulog,*)'Time-variant boundary dataset (ozone) is: ', trim(bndtvo) - if (ozncyc) then - write(iulog,*)'OZONE dataset will be reused for each model year' - else - write(iulog,*)'OZONE dataset will not be cycled' - end if - end if - -end subroutine cam3_ozone_data_init - -!================================================================================================ - -subroutine cam3_ozone_data_timestep_init(pbuf2d, phys_state) -!----------------------------------------------------------------------- -! -! Purpose: Interpolate ozone mixing ratios to current time, reading in new monthly -! data if necessary, and spatially interpolating it. -! -! Method: Find next month of ozone data to interpolate. Linearly interpolate -! vertically and horizontally -! -!----------------------------------------------------------------------- - - - use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_get_chunk - - - type(physics_state), intent(in) :: phys_state(begchunk:endchunk) - type(physics_buffer_desc), pointer :: pbuf2d(:,:) - real(r8),pointer :: tmpptr(:,:) - - integer lchnk - - call boundarydata_update(phys_state, ozonedata) - - do lchnk = begchunk, endchunk - call pbuf_get_field(pbuf_get_chunk(pbuf2d, lchnk), oz_idx, tmpptr) - call ozone_data_get_cnst(phys_state(lchnk), tmpptr) - enddo - -end subroutine cam3_ozone_data_timestep_init - -!================================================================================================ - -subroutine ozone_data_get_cnst(state, q) - - use cam_history, only: outfld - use physconst, only: mwo3 - - type(physics_state), intent(in) :: state - real(r8) :: q(:,:) ! constituent mass mixing ratio - - ! local variables - integer :: lchnk ! chunk identifier - integer :: i, k - real(r8) :: ozmixin(pcols,ozonedata%levsiz) - ! *** N.B. this hardwired mw of dry air needs to be changed to the share value - real(r8), parameter :: mwdry = 28.9644_r8 ! Effective molecular weight of dry air (g/mol) - real(r8), parameter :: mwr = mwo3/mwdry ! convert from the dataset values of vmr to mmr - !------------------------------------------------------------------------------- - - lchnk = state%lchnk - - ozmixin=0._r8 - do k=1,ozonedata%levsiz - do i=1,state%ncol - ozmixin(i,k) = ozonedata%datainst(state%latmapback(i),k,lchnk,1) - end do - end do - call boundarydata_vert_interp(lchnk, state%ncol, ozonedata%levsiz, & - 1, ozonedata%pin, state%pmid, ozmixin , q) - - call outfld('O3VMR', q, pcols, lchnk) - - do k=1,pver - do i=1,state%ncol - q(i,k) = mwr*q(i,k) - end do - end do - -end subroutine ozone_data_get_cnst - -!================================================================================================ - -end module cam3_ozone_data - diff --git a/src/physics/cam/convect_shallow.F90 b/src/physics/cam/convect_shallow.F90 index daed093b67..902187eb24 100644 --- a/src/physics/cam/convect_shallow.F90 +++ b/src/physics/cam/convect_shallow.F90 @@ -250,7 +250,7 @@ subroutine convect_shallow_init(pref_edge, pbuf2d) call add_default( 'CMFDICE ', history_budget_histfile_num, ' ' ) call add_default( 'CMFDT ', history_budget_histfile_num, ' ' ) call add_default( 'CMFDQ ', history_budget_histfile_num, ' ' ) - if( cam_physpkg_is('cam3') .or. cam_physpkg_is('cam4') ) then + if( cam_physpkg_is('cam4') ) then call add_default( 'EVAPQCM ', history_budget_histfile_num, ' ' ) call add_default( 'EVAPTCM ', history_budget_histfile_num, ' ' ) end if diff --git a/src/physics/cam/eddy_diff.F90 b/src/physics/cam/eddy_diff.F90 index de50778cbd..b48e7ed137 100644 --- a/src/physics/cam/eddy_diff.F90 +++ b/src/physics/cam/eddy_diff.F90 @@ -632,7 +632,7 @@ subroutine caleddy( pcols , pver , ncol , kvh_in , kvm_in , kvh , kvm , & tpert , qpert , qrlin , kvf , tke , & wstarent , bprod , sprod , minpblh , wpert , & - tkes , went , turbtype , sm_aw , & + tkes , went , turbtype , & kbase_o , ktop_o , ncvfin_o , & kbase_mg , ktop_mg , ncvfin_mg , & kbase_f , ktop_f , ncvfin_f , & @@ -752,8 +752,6 @@ subroutine caleddy( pcols , pver , ncol , ! 3. = Bottom external interface of CL ! 4. = Top external interface of CL. ! 5. = Double entraining CL external interface - real(r8), intent(out) :: sm_aw(pcols,pver+1) ! Galperin instability function of momentum for use in the microphysics - ! [ no unit ] integer(i4), intent(out) :: ipbl(pcols) ! If 1, PBL is CL, while if 0, PBL is STL. integer(i4), intent(out) :: kpblh(pcols) ! Layer index containing PBL within or at the base interface real(r8), intent(out) :: wsed_CL(pcols,ncvmax) ! Sedimentation velocity at the top of each CL [ m/s ] @@ -1002,7 +1000,6 @@ subroutine caleddy( pcols , pver , ncol , sh_a(i,:pver+1) = 0._r8 sm_a(i,:pver+1) = 0._r8 ri_a(i,:pver+1) = 0._r8 - sm_aw(i,:pver+1) = 0._r8 ipbl(i) = 0 kpblh(i) = pver wsed_CL(i,:ncvmax) = 0._r8 @@ -1844,7 +1841,6 @@ subroutine caleddy( pcols , pver , ncol , bprod(i,k) = -kvh(i,k) * n2(i,k) sprod(i,k) = kvm(i,k) * s2(i,k) turbtype(i,k) = 2 ! CL interior interfaces. - sm_aw(i,k) = smcl(i,ncv)/alph1 ! Diagnostic output for microphysics end do ! 2. At CL top entrainment interface @@ -1860,7 +1856,6 @@ subroutine caleddy( pcols , pver , ncol , rcap = min( max(rcap,rcapmin), rcapmax ) tke(i,kt) = ebrk(i,ncv) * rcap tke(i,kt) = min( tke(i,kt), tkemax ) - sm_aw(i,kt) = smcl(i,ncv) / alph1 ! Diagnostic output for microphysics ! 3. At CL base entrainment interface and double entraining interfaces ! When current CL base is also the top interface of CL regime below, @@ -1921,12 +1916,6 @@ subroutine caleddy( pcols , pver , ncol , end if - ! For double entraining interface, simply use smcl(i,ncv) of the overlying CL. - ! Below 'sm_aw' is a diagnostic output for use in the microphysics. - ! When 'kb' is surface, 'sm' will be over-written later below. - - sm_aw(i,kb) = smcl(i,ncv)/alph1 - ! Calculate wcap at all interfaces of CL. Put a minimum threshold on TKE ! to prevent possible division by zero. 'wcap' at CL internal interfaces ! are already calculated in the first part of 'do ncv' loop correctly. @@ -2122,8 +2111,6 @@ subroutine caleddy( pcols , pver , ncol , bprod(i,k) = -kvh(i,k) * n2(i,k) sprod(i,k) = kvm(i,k) * s2(i,k) - sm_aw(i,k) = sm/alph1 ! This is diagnostic output for use in the microphysics - end if end do ! k @@ -2192,7 +2179,6 @@ subroutine caleddy( pcols , pver , ncol , wcap(i,k) = tke_imsi / b1 bprod(i,k) = -kvh_imsi * n2(i,k) sprod(i,k) = kvm_imsi * s2(i,k) - sm_aw(i,k) = sm/alph1 ! This is diagnostic output for use in the microphysics turbtype(i,k) = 1 ! This was added on Dec.10.2009 for use in microphysics. endif @@ -2257,7 +2243,6 @@ subroutine caleddy( pcols , pver , ncol , else sm_a(i,pver+1) = max(0._r8,(alph1+alph2*gh)/(1._r8+alph3*gh)/(1._r8+alph4exs*gh)) endif - sm_aw(i,pver+1) = sm_a(i,pver+1)/alph1 ri_a(i,pver+1) = -(sm_a(i,pver+1)/sh_a(i,pver+1))*(bprod(i,pver+1)/sprod(i,pver+1)) do k = 1, pver diff --git a/src/physics/cam/eddy_diff_cam.F90 b/src/physics/cam/eddy_diff_cam.F90 index f8660e35f1..1742bf5038 100644 --- a/src/physics/cam/eddy_diff_cam.F90 +++ b/src/physics/cam/eddy_diff_cam.F90 @@ -321,7 +321,7 @@ subroutine eddy_diff_tend(state, pbuf, cam_in, & ztodt, p, tint, rhoi, cldn, wstarent, & kvm_in, kvh_in, ksrftms, dragblj,tauresx, tauresy, & rrho, ustar, pblh, kvm, kvh, kvq, cgh, cgs, tpert, qpert, & - tke, sprod, sfi, turbtype, sm_aw) + tke, sprod, sfi) use physics_types, only: physics_state use camsrfexch, only: cam_in_t @@ -355,8 +355,6 @@ subroutine eddy_diff_tend(state, pbuf, cam_in, & real(r8), intent(out) :: tke(pcols,pver+1) real(r8), intent(out) :: sprod(pcols,pver+1) real(r8), intent(out) :: sfi(pcols,pver+1) - integer(i4), intent(out) :: turbtype(pcols,pver+1) - real(r8), intent(out) :: sm_aw(pcols,pver+1) integer :: i, k @@ -370,7 +368,7 @@ subroutine eddy_diff_tend(state, pbuf, cam_in, & kvh , kvq , cgh , & cgs , tpert , qpert , tke , & sprod , sfi , & - tauresx , tauresy , ksrftms , dragblj , turbtype , sm_aw ) + tauresx , tauresy , ksrftms , dragblj ) ! The diffusivities from diag_TKE can be much larger than from HB in the free ! troposphere and upper atmosphere. These seem to be larger than observations, @@ -416,7 +414,7 @@ subroutine compute_eddy_diff( pbuf, lchnk , ustar , pblh , kvm_in , kvh_in , kvm_out , kvh_out , kvq , & cgh , cgs , tpert , qpert , tke , & sprod , sfi , & - tauresx, tauresy, ksrftms, dragblj, turbtype, sm_aw ) + tauresx, tauresy, ksrftms, dragblj ) !-------------------------------------------------------------------- ! ! Purpose: Interface to compute eddy diffusivities. ! @@ -490,10 +488,6 @@ subroutine compute_eddy_diff( pbuf, lchnk , real(r8), intent(out) :: tke(pcols,pver+1) ! Turbulent kinetic energy [ m2/s2 ] real(r8), intent(out) :: sprod(pcols,pver+1) ! Shear production [ m2/s3 ] real(r8), intent(out) :: sfi(pcols,pver+1) ! Interfacial layer saturation fraction [ fraction ] - integer(i4), intent(out):: turbtype(pcols,pver+1) ! Turbulence type identifier at all interfaces [ no unit ] - real(r8), intent(out) :: sm_aw(pcols,pver+1) ! Normalized Galperin instability function for momentum [ no unit ] - ! This is 1 when neutral condition (Ri=0), - ! 4.964 for maximum unstable case, and 0 when Ri > Ricrit=0.19. ! ---------------------- ! ! Input-Output Variables ! @@ -623,6 +617,8 @@ subroutine compute_eddy_diff( pbuf, lchnk , ! For sedimentation-entrainment feedback real(r8) :: wsed(pcols,ncvmax) ! Sedimentation velocity at the top of each CL [ m/s ] + integer(i4) :: turbtype(pcols,pver+1) ! Turbulence type identifier at all interfaces [ no unit ] + ! ---------- ! ! Parameters ! ! ---------- ! @@ -738,7 +734,7 @@ subroutine compute_eddy_diff( pbuf, lchnk , kvh , kvm , kvh_out , kvm_out , & tpert , qpert , qrl , kvf , tke , & wstarent , bprod , sprod , minpblh , wpert , & - tkes , went , turbtype , sm_aw , & + tkes , went , turbtype , & kbase_o , ktop_o , ncvfin_o , & kbase_mg , ktop_mg , ncvfin_mg , & kbase_f , ktop_f , ncvfin_f , & diff --git a/src/physics/cam/gw_common.F90 b/src/physics/cam/gw_common.F90 index ae91ec08ce..04014c8c97 100644 --- a/src/physics/cam/gw_common.F90 +++ b/src/physics/cam/gw_common.F90 @@ -98,7 +98,7 @@ module gw_common real(r8) :: dc ! Reference speeds [m/s]. real(r8), allocatable :: cref(:) - ! Critical Froude number, squared (usually 1, but CAM3 used 0.5). + ! Critical Froude number, squared real(r8) :: fcrit2 ! Horizontal wave number [1/m]. real(r8) :: kwv diff --git a/src/physics/cam/gw_drag.F90 b/src/physics/cam/gw_drag.F90 index aeab27a5c6..798ad63059 100644 --- a/src/physics/cam/gw_drag.F90 +++ b/src/physics/cam/gw_drag.F90 @@ -235,14 +235,9 @@ subroutine gw_drag_readnl(nlfile) integer :: pgwv_long = -1 real(r8) :: gw_dc_long = unset_r8 - ! fcrit2 for the mid-scale waves has been made a namelist variable to - ! facilitate backwards compatibility with the CAM3 version of this - ! parameterization. In CAM3, fcrit2=0.5. - real(r8) :: fcrit2 = unset_r8 ! critical froude number squared - namelist /gw_drag_nl/ pgwv, gw_dc, pgwv_long, gw_dc_long, tau_0_ubc, & effgw_beres_dp, effgw_beres_sh, effgw_cm, effgw_cm_igw, effgw_oro, & - fcrit2, frontgfc, gw_drag_file, gw_drag_file_sh, gw_drag_file_mm, taubgnd, & + frontgfc, gw_drag_file, gw_drag_file_sh, gw_drag_file_mm, taubgnd, & taubgnd_igw, gw_polar_taper, & use_gw_rdg_beta, n_rdg_beta, effgw_rdg_beta, effgw_rdg_beta_max, & rdg_beta_cd_llb, trpd_leewv_rdg_beta, & @@ -320,8 +315,6 @@ subroutine gw_drag_readnl(nlfile) call mpi_bcast(gw_oro_south_fac, 1, mpi_real8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_oro_south_fac") - call mpi_bcast(fcrit2, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: fcrit2") call mpi_bcast(frontgfc, 1, mpi_real8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: frontgfc") call mpi_bcast(taubgnd, 1, mpi_real8, mstrid, mpicom, ierr) @@ -359,11 +352,6 @@ subroutine gw_drag_readnl(nlfile) call mpi_bcast(alpha_gw_movmtn, 1, mpi_real8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: alpha_gw_movmtn") - ! Check if fcrit2 was set. - call shr_assert(fcrit2 /= unset_r8, & - "gw_drag_readnl: fcrit2 must be set via the namelist."// & - errMsg(__FILE__, __LINE__)) - ! Check if pgwv was set. call shr_assert(pgwv >= 0, & "gw_drag_readnl: pgwv must be set via the namelist and & @@ -375,7 +363,7 @@ subroutine gw_drag_readnl(nlfile) "gw_drag_readnl: gw_dc must be set via the namelist."// & errMsg(__FILE__, __LINE__)) - band_oro = GWBand(0, gw_dc, fcrit2, wavelength_mid) + band_oro = GWBand(0, gw_dc, 1.0_r8, wavelength_mid) band_mid = GWBand(pgwv, gw_dc, 1.0_r8, wavelength_mid) band_long = GWBand(pgwv_long, gw_dc_long, 1.0_r8, wavelength_long) band_movmtn = GWBand(0, gw_dc, 1.0_r8, wavelength_mid) @@ -1716,7 +1704,13 @@ subroutine gw_tend(state, pbuf, dt, ptend, cam_in, flx_heat) call alloc_err(istat,'gw_tend','phase_speeds',ncol*band_movmtn%ngwv**2+1) ! Set up heating - call pbuf_get_field(pbuf, ttend_dp_idx, ttend_dp) + if (ttend_dp_idx > 0) then + call pbuf_get_field(pbuf, ttend_dp_idx, ttend_dp) + else + allocate(ttend_dp(pcols,pver), stat=istat) + call alloc_err(istat, 'gw_tend', 'ttend_dp', pcols*pver) + ttend_dp = 0.0_r8 + end if ! New couplings from CLUBB call pbuf_get_field(pbuf, ttend_clubb_idx, ttend_clubb) @@ -1789,7 +1783,15 @@ subroutine gw_tend(state, pbuf, dt, ptend, cam_in, flx_heat) call outfld('UPWP_CLUBB_GW', upwp_clubb_gw, pcols, lchnk) call outfld('VPWP_CLUBB_GW', vpwp_clubb_gw, pcols, lchnk) + !Deallocate variables that are no longer used: deallocate(tau, gwut, phase_speeds) + + !Deallocate/nullify ttend_dp if not a pbuf variable: + if (ttend_dp_idx <= 0) then + deallocate(ttend_dp) + nullify(ttend_dp) + end if + end if if (use_gw_convect_dp) then diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index e6d062e027..d4c362f391 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -130,8 +130,6 @@ subroutine phys_register use tracers, only: tracers_register use check_energy, only: check_energy_register use carma_intr, only: carma_register - use cam3_aero_data, only: cam3_aero_data_on, cam3_aero_data_register - use cam3_ozone_data, only: cam3_ozone_data_on, cam3_ozone_data_register use ghg_data, only: ghg_data_register use vertical_diffusion, only: vd_register use convect_deep, only: convect_deep_register @@ -281,9 +279,6 @@ subroutine phys_register call co2_register() ! register data model ozone with pbuf - if (cam3_ozone_data_on) then - call cam3_ozone_data_register() - end if call prescribed_volcaero_register() call prescribed_strataero_register() call prescribed_ozone_register() @@ -291,11 +286,6 @@ subroutine phys_register call prescribed_ghg_register() call sslt_rebin_register - ! CAM3 prescribed aerosols - if (cam3_aero_data_on) then - call cam3_aero_data_register() - end if - ! register various data model gasses with pbuf call ghg_data_register() @@ -743,8 +733,6 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) use convect_shallow, only: convect_shallow_init use cam_diagnostics, only: diag_init use gw_drag, only: gw_init - use cam3_aero_data, only: cam3_aero_data_on, cam3_aero_data_init - use cam3_ozone_data, only: cam3_ozone_data_on, cam3_ozone_data_init use radheat, only: radheat_init use radiation, only: radiation_init use cloud_diagnostics, only: cloud_diagnostics_init @@ -859,9 +847,6 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) ! solar irradiance data modules call solar_data_init() - ! CAM3 prescribed aerosols - if (cam3_aero_data_on) call cam3_aero_data_init(phys_state) - ! Initialize rad constituents and their properties call rad_cnst_init() @@ -892,9 +877,6 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call co2_init() end if - ! CAM3 prescribed ozone - if (cam3_ozone_data_on) call cam3_ozone_data_init(phys_state) - call gw_init() call rayleigh_friction_init() @@ -2940,8 +2922,6 @@ subroutine phys_timestep_init(phys_state, cam_in, cam_out, pbuf2d) use physics_buffer, only: physics_buffer_desc use carma_intr, only: carma_timestep_init use ghg_data, only: ghg_data_timestep_init - use cam3_aero_data, only: cam3_aero_data_on, cam3_aero_data_timestep_init - use cam3_ozone_data, only: cam3_ozone_data_on, cam3_ozone_data_timestep_init use aoa_tracers, only: aoa_tracers_timestep_init use vertical_diffusion, only: vertical_diffusion_ts_init use radheat, only: radheat_timestep_init @@ -3005,12 +2985,6 @@ subroutine phys_timestep_init(phys_state, cam_in, cam_out, pbuf2d) ! prescribed aerosol deposition fluxes call aerodep_flx_adv(phys_state, pbuf2d, cam_out) - ! CAM3 prescribed aerosol masses - if (cam3_aero_data_on) call cam3_aero_data_timestep_init(pbuf2d, phys_state) - - ! CAM3 prescribed ozone data - if (cam3_ozone_data_on) call cam3_ozone_data_timestep_init(pbuf2d, phys_state) - ! Time interpolate data models of gasses in pbuf2d call ghg_data_timestep_init(pbuf2d, phys_state) diff --git a/src/physics/cam/rk_stratiform.F90 b/src/physics/cam/rk_stratiform.F90 index 84607a20b7..a6bcf39be7 100644 --- a/src/physics/cam/rk_stratiform.F90 +++ b/src/physics/cam/rk_stratiform.F90 @@ -3,7 +3,7 @@ module rk_stratiform !------------------------------------------------------------------------------------------------------- ! ! Provides the CAM interface to the Rasch and Kristjansson (RK) -! prognostic cloud microphysics, and the cam3/4 macrophysics. +! prognostic cloud microphysics, and the cam4 macrophysics. ! !------------------------------------------------------------------------------------------------------- @@ -356,7 +356,7 @@ subroutine rk_stratiform_init() call add_default ('EVAPPREC ', history_budget_histfile_num, ' ') call add_default ('CMELIQ ', history_budget_histfile_num, ' ') - if( cam_physpkg_is('cam3') .or. cam_physpkg_is('cam4') ) then + if( cam_physpkg_is('cam4') ) then call add_default ('ZMDLF ', history_budget_histfile_num, ' ') call add_default ('CME ', history_budget_histfile_num, ' ') @@ -954,20 +954,16 @@ subroutine rk_stratiform_tend( & call physics_ptend_sum( ptend_loc, ptend_all, ncol ) call physics_update( state1, ptend_loc, dtime ) - if (.not. cam_physpkg_is('cam3')) then - - call t_startf("cldfrc") - call cldfrc( lchnk, ncol, pbuf, & - state1%pmid, state1%t, state1%q(:,:,1), state1%omega, state1%phis, & - shfrc, use_shfrc, & - cld, rhcloud, clc, state1%pdel, & - cmfmc, cmfmc_sh, landfrac, snowh, concld, cldst, & - ts, sst, state1%pint(:,pverp), zdu, ocnfrac, rhu00, & - state1%q(:,:,ixcldice), icecldf, liqcldf, & - relhum, 0 ) - call t_stopf("cldfrc") - - endif + call t_startf("cldfrc") + call cldfrc( lchnk, ncol, pbuf, & + state1%pmid, state1%t, state1%q(:,:,1), state1%omega, state1%phis, & + shfrc, use_shfrc, & + cld, rhcloud, clc, state1%pdel, & + cmfmc, cmfmc_sh, landfrac, snowh, concld, cldst, & + ts, sst, state1%pint(:,pverp), zdu, ocnfrac, rhu00, & + state1%q(:,:,ixcldice), icecldf, liqcldf, & + relhum, 0 ) + call t_stopf("cldfrc") call outfld( 'CONCLD ', concld, pcols, lchnk ) call outfld( 'CLDST ', cldst, pcols, lchnk ) diff --git a/src/physics/cam/uwshcu.F90 b/src/physics/cam/uwshcu.F90 index 914d131a94..a5e5a0c6ea 100644 --- a/src/physics/cam/uwshcu.F90 +++ b/src/physics/cam/uwshcu.F90 @@ -3765,7 +3765,7 @@ subroutine compute_uwshcu( mix , mkx , iend , ncnst , dt ! -------------------------------------------------------------------------- ! ! 'rliq' : Verticall-integrated 'suspended cloud condensate' ! ! [m/s] This is so called 'reserved liquid water' in other subroutines ! - ! of CAM3, since the contribution of this term should not be included into ! + ! of CAM, since the contribution of this term should not be included into ! ! the tendency of each layer or surface flux (precip) within this cumulus ! ! scheme. The adding of this term to the layer tendency will be done inthe ! ! 'stratiform_tend', just after performing sediment process there. ! @@ -3928,9 +3928,9 @@ subroutine compute_uwshcu( mix , mkx , iend , ncnst , dt ! --------------------------------------------------------------------------- ! ! Until now, all the calculations are done completely in this shallow cumulus ! - ! scheme. If you want to use this cumulus scheme other than CAM3, then do not ! + ! scheme. If you want to use this cumulus scheme other than CAM, then do not ! ! perform below block. However, for compatible use with the other subroutines ! - ! in CAM3, I should subtract the effect of 'qc(k)' ('rliq') from the tendency ! + ! in CAM, I should subtract the effect of 'qc(k)' ('rliq') from the tendency ! ! equation in each layer, since this effect will be separately added later in ! ! in 'stratiform_tend' just after performing sediment process there. In order ! ! to be consistent with 'stratiform_tend', just subtract qc(k) from tendency ! diff --git a/src/physics/cam/vertical_diffusion.F90 b/src/physics/cam/vertical_diffusion.F90 index 507e99dc8d..472b2a5501 100644 --- a/src/physics/cam/vertical_diffusion.F90 +++ b/src/physics/cam/vertical_diffusion.F90 @@ -105,7 +105,6 @@ module vertical_diffusion type(vdiff_selector) :: fieldlist_molec ! Logical switches for molecular diffusion integer :: tke_idx, kvh_idx, kvm_idx ! TKE and eddy diffusivity indices for fields in the physics buffer integer :: kvt_idx ! Index for kinematic molecular conductivity -integer :: turbtype_idx, smaw_idx ! Turbulence type and instability functions integer :: tauresx_idx, tauresy_idx ! Redisual stress for implicit surface stress character(len=fieldname_len) :: vdiffnam(pcnst) ! Names of vertical diffusion tendencies @@ -228,8 +227,6 @@ subroutine vd_register() call pbuf_add_field('kvm', 'global', dtype_r8, (/pcols, pverp/), kvm_idx ) call pbuf_add_field('pblh', 'global', dtype_r8, (/pcols/), pblh_idx) call pbuf_add_field('tke', 'global', dtype_r8, (/pcols, pverp/), tke_idx) - call pbuf_add_field('turbtype', 'global', dtype_i4, (/pcols, pverp/), turbtype_idx) - call pbuf_add_field('smaw', 'global', dtype_r8, (/pcols, pverp/), smaw_idx) call pbuf_add_field('tauresx', 'global', dtype_r8, (/pcols/), tauresx_idx) call pbuf_add_field('tauresy', 'global', dtype_r8, (/pcols/), tauresy_idx) @@ -665,8 +662,6 @@ subroutine vertical_diffusion_init(pbuf2d) ! Initialization of some pbuf fields if (is_first_step()) then ! Initialization of pbuf fields tke, kvh, kvm are done in phys_inidat - call pbuf_set_field(pbuf2d, turbtype_idx, 0 ) - call pbuf_set_field(pbuf2d, smaw_idx, 0.0_r8) call pbuf_set_field(pbuf2d, tauresx_idx, 0.0_r8) call pbuf_set_field(pbuf2d, tauresy_idx, 0.0_r8) if (trim(shallow_scheme) == 'UNICON') then @@ -773,9 +768,6 @@ subroutine vertical_diffusion_tend( & real(r8) :: dtk(pcols,pver) ! T tendency from KE dissipation real(r8), pointer :: tke(:,:) ! Turbulent kinetic energy [ m2/s2 ] - integer(i4),pointer :: turbtype(:,:) ! Turbulent interface types [ no unit ] - real(r8), pointer :: smaw(:,:) ! Normalized Galperin instability function - ! ( 0<= <=4.964 and 1 at neutral ) real(r8), pointer :: qtl_flx(:,:) ! overbar(w'qtl') where qtl = qv + ql real(r8), pointer :: qti_flx(:,:) ! overbar(w'qti') where qti = qv + qi @@ -922,7 +914,6 @@ subroutine vertical_diffusion_tend( & call pbuf_get_field(pbuf, tpert_idx, tpert) call pbuf_get_field(pbuf, qpert_idx, qpert) call pbuf_get_field(pbuf, pblh_idx, pblh) - call pbuf_get_field(pbuf, turbtype_idx, turbtype) ! Interpolate temperature to interfaces. do k = 2, pver @@ -1015,7 +1006,6 @@ subroutine vertical_diffusion_tend( & !----------------------------------------------------------------------- ! call pbuf_get_field(pbuf, kvm_idx, kvm_in) call pbuf_get_field(pbuf, kvh_idx, kvh_in) - call pbuf_get_field(pbuf, smaw_idx, smaw) call pbuf_get_field(pbuf, tke_idx, tke) ! Get potential temperature. @@ -1028,7 +1018,7 @@ subroutine vertical_diffusion_tend( & ztodt, p, tint, rhoi, cldn, wstarent, & kvm_in, kvh_in, ksrftms, dragblj, tauresx, tauresy, & rrho, ustar, pblh, kvm, kvh, kvq, cgh, cgs, tpert, qpert, & - tke, sprod, sfi, turbtype, smaw) + tke, sprod, sfi) ! The diag_TKE scheme does not calculate the Monin-Obukhov length, which is used in dry deposition calculations. ! Use the routines from pbl_utils to accomplish this. Assumes ustar and rrho have been set. diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 62cd8bfca3..fa33c50856 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -766,23 +766,21 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call physics_update(state1, ptend_loc, ztodt) - ! Momentum Transport (non-cam3 physics) + ! Momentum Transport - if ( .not. cam_physpkg_is('cam3')) then + call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_momtran_run', ls=.true., lu=.true., lv=.true.) - call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_momtran_run', ls=.true., lu=.true., lv=.true.) - - l_windt(1) = .true. - l_windt(2) = .true. + l_windt(1) = .true. + l_windt(2) = .true. !REMOVECAM - no longer need these when CAM is retired and pcols no longer exists - ptend_loc%s(:,:) = 0._r8 - ptend_loc%u(:,:) = 0._r8 - ptend_loc%v(:,:) = 0._r8 + ptend_loc%s(:,:) = 0._r8 + ptend_loc%u(:,:) = 0._r8 + ptend_loc%v(:,:) = 0._r8 !REMOVECAM_END - call t_startf ('zm_conv_momtran_run') + call t_startf ('zm_conv_momtran_run') - call zm_conv_momtran_run (ncol, pver, pverp, & + call zm_conv_momtran_run (ncol, pver, pverp, & l_windt,state1%u(:ncol,:), state1%v(:ncol,:), 2, mu(:ncol,:), md(:ncol,:), & zmconv_momcu, zmconv_momcd, & du(:ncol,:), eu(:ncol,:), ed(:ncol,:), dp(:ncol,:), dsubcld(:ncol), & @@ -790,47 +788,45 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & nstep, ptend_loc%u(:ncol,:), ptend_loc%v(:ncol,:),& pguallu(:ncol,:), pguallv(:ncol,:), pgdallu(:ncol,:), pgdallv(:ncol,:), & icwuu(:ncol,:), icwuv(:ncol,:), icwdu(:ncol,:), icwdv(:ncol,:), ztodt, seten(:ncol,:) ) - call t_stopf ('zm_conv_momtran_run') - - ptend_loc%s(:ncol,:pver) = seten(:ncol,:pver) - - call physics_ptend_sum(ptend_loc,ptend_all, ncol) - - ! Output ptend variables before they are set to zero with physics_update - call outfld('ZMMTU', ptend_loc%u, pcols, lchnk) - call outfld('ZMMTV', ptend_loc%v, pcols, lchnk) - - ! update physics state type state1 with ptend_loc - call physics_update(state1, ptend_loc, ztodt) - - ftem(:ncol,:pver) = seten(:ncol,:pver)/cpair - if (zmconv_org) then - call outfld('ZM_ORG', state%q(:,:,ixorg), pcols, lchnk) - call outfld('ZM_ORG2D', zm_org2d, pcols, lchnk) - endif - call outfld('ZMMTT', ftem , pcols, lchnk) + call t_stopf ('zm_conv_momtran_run') - ! Output apparent force from pressure gradient - call outfld('ZMUPGU', pguallu, pcols, lchnk) - call outfld('ZMUPGD', pgdallu, pcols, lchnk) - call outfld('ZMVPGU', pguallv, pcols, lchnk) - call outfld('ZMVPGD', pgdallv, pcols, lchnk) + ptend_loc%s(:ncol,:pver) = seten(:ncol,:pver) - ! Output in-cloud winds - call outfld('ZMICUU', icwuu, pcols, lchnk) - call outfld('ZMICUD', icwdu, pcols, lchnk) - call outfld('ZMICVU', icwuv, pcols, lchnk) - call outfld('ZMICVD', icwdv, pcols, lchnk) + call physics_ptend_sum(ptend_loc,ptend_all, ncol) - end if + ! Output ptend variables before they are set to zero with physics_update + call outfld('ZMMTU', ptend_loc%u, pcols, lchnk) + call outfld('ZMMTV', ptend_loc%v, pcols, lchnk) - ! Transport cloud water and ice only - call cnst_get_ind('CLDLIQ', ixcldliq) - call cnst_get_ind('CLDICE', ixcldice) + ! update physics state type state1 with ptend_loc + call physics_update(state1, ptend_loc, ztodt) - lq(:) = .FALSE. - lq(2:) = cnst_is_convtran1(2:) - call physics_ptend_init(ptend_loc, state1%psetcols, 'convtran1', lq=lq) + ftem(:ncol,:pver) = seten(:ncol,:pver)/cpair + if (zmconv_org) then + call outfld('ZM_ORG', state%q(:,:,ixorg), pcols, lchnk) + call outfld('ZM_ORG2D', zm_org2d, pcols, lchnk) + endif + call outfld('ZMMTT', ftem , pcols, lchnk) + + ! Output apparent force from pressure gradient + call outfld('ZMUPGU', pguallu, pcols, lchnk) + call outfld('ZMUPGD', pgdallu, pcols, lchnk) + call outfld('ZMVPGU', pguallv, pcols, lchnk) + call outfld('ZMVPGD', pgdallv, pcols, lchnk) + + ! Output in-cloud winds + call outfld('ZMICUU', icwuu, pcols, lchnk) + call outfld('ZMICUD', icwdu, pcols, lchnk) + call outfld('ZMICVU', icwuv, pcols, lchnk) + call outfld('ZMICVD', icwdv, pcols, lchnk) + + ! Transport cloud water and ice only + call cnst_get_ind('CLDLIQ', ixcldliq) + call cnst_get_ind('CLDICE', ixcldice) + + lq(:) = .FALSE. + lq(2:) = cnst_is_convtran1(2:) + call physics_ptend_init(ptend_loc, state1%psetcols, 'convtran1', lq=lq) ! dpdry is not used in this call to convtran since the cloud liquid and ice mixing diff --git a/src/physics/camrt/radconstants.F90 b/src/physics/camrt/radconstants.F90 index c95c8d2154..f9faf308f1 100644 --- a/src/physics/camrt/radconstants.F90 +++ b/src/physics/camrt/radconstants.F90 @@ -1,7 +1,7 @@ module radconstants ! This module contains constants that are specific to the radiative transfer -! code used in the CAM3 model. +! code used in the CAM4 model. use shr_kind_mod, only: r8 => shr_kind_r8 use cam_abortutils, only: endrun diff --git a/src/physics/camrt/radlw.F90 b/src/physics/camrt/radlw.F90 index 62ec514ffc..befd69fbc9 100644 --- a/src/physics/camrt/radlw.F90 +++ b/src/physics/camrt/radlw.F90 @@ -435,11 +435,7 @@ subroutine radclwmx(lchnk ,ncol ,doabsems , & ntopcld = max(ntopcld, trop_cloud_top_lev) cldp(:ncol,1:ntopcld) = 0.0_r8 - if ( cam_physpkg_is('cam3')) then - cldp(:ncol,ntoplw:pver) = cld(:ncol,ntoplw:pver) - else - cldp(:ncol,ntopcld+1:pver) = cld(:ncol,ntopcld+1:pver) - end if + cldp(:ncol,ntopcld+1:pver) = cld(:ncol,ntopcld+1:pver) cldp(:ncol,pverp) = 0.0_r8 ! ! diff --git a/src/physics/rrtmg/aer_src/rrtmg_sw_init.f90 b/src/physics/rrtmg/aer_src/rrtmg_sw_init.f90 index d71fa2a897..fc2ec91a53 100644 --- a/src/physics/rrtmg/aer_src/rrtmg_sw_init.f90 +++ b/src/physics/rrtmg/aer_src/rrtmg_sw_init.f90 @@ -182,10 +182,6 @@ subroutine swdatinit ! = (9.8066)(86400)(1e-5)/(1.004) ! heatfac = 8.4391_r8 -! Modified values for consistency with CAM3: -! = (9.80616)(86400)(1e-5)/(1.00464) -! heatfac = 8.43339130434_r8 - ! Calculate heatfac directly from CAM constants: heatfac = grav * cday * 1.e-5_r8 / (cpair * 1.e-3_r8)