From 7d0acfe2c7fbbc8e35aa78823da3f3e525493056 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 28 Oct 2021 11:06:40 -0600 Subject: [PATCH 01/21] Git now ignores .vscode/. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 9b97e8c3c0..afda8f5027 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,6 @@ core.* *.log !run.log *.pyc Depends + +# ssr +.vscode/ From 93607781bfe22160cd5f2bc491fb31bb5073d2de Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 26 Jan 2022 14:13:22 -0700 Subject: [PATCH 02/21] Added annual outputs of sowing and harvest dates. SDATES and HDATES, respectively. Sowing dates are on new dimension mxgrowseas (maximum number of growing seasons begun this year; currently hard-coded to 1). Harvest dates are on new dimension mxharvests, which is mxgrowseas+1. The lengths of these dimensions are public constants of clm_varpar. Cherry-picked from various commits on other branches in my fork. --- src/biogeochem/CNPhenologyMod.F90 | 72 +++++++++---------------------- src/biogeochem/CropType.F90 | 56 +++++++++++------------- src/main/clm_varpar.F90 | 4 ++ src/main/histFileMod.F90 | 18 +++++--- 4 files changed, 63 insertions(+), 87 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 1c12747d72..e6ab298a58 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -14,7 +14,7 @@ module CNPhenologyMod use shr_log_mod , only : errMsg => shr_log_errMsg use shr_sys_mod , only : shr_sys_flush use decompMod , only : bounds_type - use clm_varpar , only : maxveg, nlevdecomp_full + use clm_varpar , only : maxveg, nlevdecomp_full, mxgrowseas, mxharvests use clm_varpar , only : i_litr_min, i_litr_max use clm_varctl , only : iulog, use_cndv use clm_varcon , only : tfrz @@ -1644,7 +1644,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! handle CN fluxes during the phenological onset & offset periods. ! !USES: - use clm_time_manager , only : get_curr_date, get_curr_calday, get_curr_days_per_year, get_rad_step_size + use clm_time_manager , only : get_curr_calday, get_curr_days_per_year, get_rad_step_size, is_beg_curr_year use pftconMod , only : ntmp_corn, nswheat, nwwheat, ntmp_soybean use pftconMod , only : nirrig_tmp_corn, nirrig_swheat, nirrig_wwheat, nirrig_tmp_soybean use pftconMod , only : ntrp_corn, nsugarcane, ntrp_soybean, ncotton, nrice @@ -1673,15 +1673,12 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst ! ! LOCAL VARAIBLES: - integer kyr ! current year - integer kmo ! month of year (1, ..., 12) - integer kda ! day of month (1, ..., 31) - integer mcsec ! seconds of day (0, ..., seconds/day) integer jday ! julian day of the year integer fp,p ! patch indices integer c ! column indices integer g ! gridcell indices integer h ! hemisphere indices + integer s ! growing season indices integer idpp ! number of days past planting real(r8) :: dtrad ! radiation time step delta t (seconds) real(r8) dayspyr ! days per year @@ -1718,8 +1715,9 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & leafout => crop_inst%gddtsoi_patch , & ! Input: [real(r8) (:) ] gdd from top soil layer temperature harvdate => crop_inst%harvdate_patch , & ! Output: [integer (:) ] harvest date croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested - cropplant => crop_inst%cropplant_patch , & ! Output: [logical (:) ] Flag, true if crop may be planted vf => crop_inst%vf_patch , & ! Output: [real(r8) (:) ] vernalization factor + sowing_count => crop_inst%sowing_count , & ! Inout: [integer (:) ] number of sowing events this year for this patch + harvest_count => crop_inst%harvest_count , & ! Inout: [integer (:) ] number of harvest events this year for this patch peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow @@ -1751,7 +1749,6 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! get time info dayspyr = get_curr_days_per_year() jday = get_curr_calday() - call get_curr_date(kyr, kmo, kda, mcsec) dtrad = real( get_rad_step_size(), r8 ) if (use_fertilizer) then @@ -1776,36 +1773,22 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! from AgroIBIS subroutine planting ! --------------------------------- - ! in order to allow a crop to be planted only once each year - ! initialize cropplant = .false., but hold it = .true. through the end of the year - ! initialize other variables that are calculated for crops ! on an annual basis in cropresidue subroutine - if ( jday == jdayyrstart(h) .and. mcsec == 0 )then - - ! make sure variables aren't changed at beginning of the year - ! for a crop that is currently planted, such as - ! WINTER TEMPERATE CEREAL = winter (wheat + barley + rye) - ! represented here by the winter wheat pft - - if (.not. croplive(p)) then - cropplant(p) = .false. - idop(p) = NOT_Planted - - ! keep next for continuous, annual winter temperate cereal crop; - ! if we removed elseif, - ! winter cereal grown continuously would amount to a cereal/fallow - ! rotation because cereal would only be planted every other year - - else if (croplive(p) .and. (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then - cropplant(p) = .false. - ! else ! not possible to have croplive and ivt==cornORsoy? (slevis) - end if - + if ( is_beg_curr_year() ) then + sowing_count(p) = 0 + harvest_count(p) = 0 + do s = 1, mxgrowseas + crop_inst%sdates_thisyr(p,s) = -1._r8 + end do + do s = 1, mxharvests + crop_inst%hdates_thisyr(p,s) = -1._r8 + end do end if - if ( (.not. croplive(p)) .and. (.not. cropplant(p)) ) then + ! Once outputs can handle >1 planting per year, remove 2nd condition. + if ( (.not. croplive(p)) .and. sowing_count(p) == 0 ) then ! gdd needed for * chosen crop and a likely hybrid (for that region) * ! to reach full physiological maturity @@ -1826,22 +1809,6 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then - ! add check to only plant winter cereal after other crops (soybean, maize) - ! have been harvested - - ! *** remember order of planting is crucial - in terms of which crops you want - ! to be grown in what order *** - - ! in this case, corn or soybeans are assumed to be planted before - ! cereal would be in any particular year that both patches are allowed - ! to grow in the same grid cell (e.g., double-cropping) - - ! slevis: harvdate below needs cropplant(p) above to be cropplant(p,ivt(p)) - ! where ivt(p) has rotated to winter cereal because - ! cropplant through the end of the year for a harvested crop. - ! Also harvdate(p) should be harvdate(p,ivt(p)) and should be - ! updated on Jan 1st instead of at harvest (slevis) - ! Are all the normal requirements for planting met? do_plant_normal = a5tmin(p) /= spval .and. & a5tmin(p) <= minplanttemp(ivt(p)) .and. & @@ -2073,6 +2040,8 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + harvest_count(p) = harvest_count(p) + 1 + crop_inst%hdates_thisyr(p, harvest_count(p)) = DBLE(jday) croplive(p) = .false. ! no re-entry in greater if-block cphase(p) = 4._r8 if (tlai(p) > 0._r8) then ! plant had emerged before harvest @@ -2241,8 +2210,8 @@ subroutine PlantCrop(p, leafcn_in, jday, & associate( & croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested - cropplant => crop_inst%cropplant_patch , & ! Output: [logical (:) ] Flag, true if crop may be planted harvdate => crop_inst%harvdate_patch , & ! Output: [integer (:) ] harvest date + sowing_count => crop_inst%sowing_count , & ! Inout: [integer (:) ] number of sowing events this year for this patch idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) leaf C transfer leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) leaf N transfer @@ -2253,9 +2222,10 @@ subroutine PlantCrop(p, leafcn_in, jday, & ! impose limit on growing season length needed ! for crop maturity - for cold weather constraints croplive(p) = .true. - cropplant(p) = .true. idop(p) = jday harvdate(p) = NOT_Harvested + sowing_count(p) = sowing_count(p) + 1 + crop_inst%sdates_thisyr(p,sowing_count(p)) = jday leafc_xfer(p) = initial_seed_at_planting leafn_xfer(p) = leafc_xfer(p) / leafcn_in ! with onset diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index afa2008f13..3d8fccbc6b 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -27,11 +27,9 @@ module CropType ! Crop state variables structure type, public :: crop_type - ! Note that cropplant and harvdate could be 2D to facilitate rotation integer , pointer :: nyrs_crop_active_patch (:) ! number of years this crop patch has been active (0 for non-crop patches) logical , pointer :: croplive_patch (:) ! patch Flag, true if planted, not harvested - logical , pointer :: cropplant_patch (:) ! patch Flag, true if planted - integer , pointer :: harvdate_patch (:) ! patch harvest date + integer , pointer :: harvdate_patch (:) ! most recent patch harvest date; 999 if currently (or never) planted real(r8), pointer :: fertnitro_patch (:) ! patch fertilizer nitrogen real(r8), pointer :: gddplant_patch (:) ! patch accum gdd past planting date for crop (ddays) real(r8), pointer :: gddtsoi_patch (:) ! patch growing degree-days from planting (top two soil layers) (ddays) @@ -41,6 +39,10 @@ module CropType character(len=20) :: baset_mapping real(r8) :: baset_latvary_intercept real(r8) :: baset_latvary_slope + real(r8), pointer :: sdates_thisyr (:,:) ! all actual sowing dates for this patch this year + real(r8), pointer :: hdates_thisyr (:,:) ! all actual harvest dates for this patch this year + integer , pointer :: sowing_count (:) ! number of sowing events this year for this patch + integer , pointer :: harvest_count (:) ! number of sowing events this year for this patch contains ! Public routines @@ -177,6 +179,8 @@ end subroutine ReadNML subroutine InitAllocate(this, bounds) ! !USES: ! + use clm_varpar, only : mxgrowseas, mxharvests + ! ! !ARGUMENTS: class(crop_type) , intent(inout) :: this type(bounds_type), intent(in) :: bounds @@ -191,7 +195,6 @@ subroutine InitAllocate(this, bounds) allocate(this%nyrs_crop_active_patch(begp:endp)) ; this%nyrs_crop_active_patch(:) = 0 allocate(this%croplive_patch (begp:endp)) ; this%croplive_patch (:) = .false. - allocate(this%cropplant_patch(begp:endp)) ; this%cropplant_patch(:) = .false. allocate(this%harvdate_patch (begp:endp)) ; this%harvdate_patch (:) = huge(1) allocate(this%fertnitro_patch (begp:endp)) ; this%fertnitro_patch (:) = spval allocate(this%gddplant_patch (begp:endp)) ; this%gddplant_patch (:) = spval @@ -199,6 +202,14 @@ subroutine InitAllocate(this, bounds) allocate(this%vf_patch (begp:endp)) ; this%vf_patch (:) = 0.0_r8 allocate(this%cphase_patch (begp:endp)) ; this%cphase_patch (:) = 0.0_r8 allocate(this%latbaset_patch (begp:endp)) ; this%latbaset_patch (:) = spval + allocate(this%sdates_thisyr(begp:endp,1:mxgrowseas)) + allocate(this%hdates_thisyr(begp:endp,1:mxharvests)) + allocate(this%sowing_count(begp:endp)) ; this%sowing_count(:) = 0 + allocate(this%harvest_count(begp:endp)) ; this%harvest_count(:) = 0 + + this%rx_sdates_thisyr(:,:) = -1 + this%sdates_thisyr(:,:) = -1._r8 + this%hdates_thisyr(:,:) = -1._r8 end subroutine InitAllocate @@ -206,7 +217,7 @@ end subroutine InitAllocate subroutine InitHistory(this, bounds) ! ! !USES: - use histFileMod , only : hist_addfld1d + use histFileMod , only : hist_addfld1d, hist_addfld2d ! ! !ARGUMENTS: class(crop_type), intent(inout) :: this @@ -247,6 +258,16 @@ subroutine InitHistory(this, bounds) ptr_patch=this%latbaset_patch, default='inactive') end if + this%sdates_thisyr(begp:endp,:) = spval + call hist_addfld2d (fname='SDATES', units='day of year', type2d='mxgrowseas', & + avgflag='I', long_name='actual crop sowing dates; should only be output annually', & + ptr_patch=this%sdates_thisyr, default='inactive') + + this%hdates_thisyr(begp:endp,:) = spval + call hist_addfld2d (fname='HDATES', units='day of year', type2d='mxharvests', & + avgflag='I', long_name='actual crop harvest dates; should only be output annually', & + ptr_patch=this%hdates_thisyr, default='inactive') + end subroutine InitHistory subroutine InitCold(this, bounds) @@ -468,31 +489,6 @@ subroutine Restart(this, bounds, ncid, flag) end if deallocate(temp1d) - allocate(temp1d(bounds%begp:bounds%endp)) - if (flag == 'write') then - do p= bounds%begp,bounds%endp - if (this%cropplant_patch(p)) then - temp1d(p) = 1 - else - temp1d(p) = 0 - end if - end do - end if - call restartvar(ncid=ncid, flag=flag, varname='cropplant', xtype=ncd_log, & - dim1name='pft', & - long_name='Flag that crop is planted, but not harvested' , & - interpinic_flag='interp', readvar=readvar, data=temp1d) - if (flag == 'read') then - do p= bounds%begp,bounds%endp - if (temp1d(p) == 1) then - this%cropplant_patch(p) = .true. - else - this%cropplant_patch(p) = .false. - end if - end do - end if - deallocate(temp1d) - call restartvar(ncid=ncid, flag=flag, varname='harvdate', xtype=ncd_int, & dim1name='pft', long_name='harvest date', units='jday', nvalid_range=(/1,366/), & interpinic_flag='interp', readvar=readvar, data=this%harvdate_patch) diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index e8d62453d3..0048c9210d 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -51,6 +51,8 @@ module clm_varpar integer, public, parameter :: dst_src_nbr = 3 ! number of size distns in src soil (BGC only) integer, public, parameter :: sz_nbr = 200 ! number of sub-grid bins in large bin of dust size distribution (BGC only) integer, public, parameter :: mxpft = 78 ! maximum number of PFT's for any mode; + integer, public, parameter :: mxgrowseas = 1 ! maximum number of crop growing seasons to begin in any year; + integer, public :: mxharvests ! maximum number of crop harvests in any year; ! FIX(RF,032414) might we set some of these automatically from reading pft-physiology? integer, public, parameter :: nlayer = 3 ! number of VIC soil layer --Added by AWang integer, public :: nlayert ! number of VIC soil layer + 3 lower thermal layers @@ -142,6 +144,8 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) cft_lb = natpft_ub + 1 cft_ub = cft_lb + cft_size - 1 + mxharvests = mxgrowseas + 1 + ! TODO(wjs, 2015-10-04, bugz 2227) Using actual_numcft in this 'max' gives a significant ! overestimate of max_patch_per_col when use_crop is true. This should be reworked - ! or, better, removed from the code entirely (because it is a maintenance problem, and diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index c8045e06aa..68acbe12c6 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -193,7 +193,7 @@ module histFileMod character(len=max_chars) :: units ! units character(len=hist_dim_name_length) :: type1d ! pointer to first dimension type from data type (nameg, etc) character(len=hist_dim_name_length) :: type1d_out ! hbuf first dimension type from data type (nameg, etc) - character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)"] + character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)","mxgrowseas","mxharvests"] integer :: beg1d ! on-node 1d clm pointer start index integer :: end1d ! on-node 1d clm pointer end index integer :: num1d ! size of clm pointer first dimension (all nodes) @@ -1271,7 +1271,7 @@ subroutine hist_update_hbuf(bounds) integer :: num2d ! size of second dimension (e.g. number of vertical levels) integer :: numdims ! number of dimensions character(len=*),parameter :: subname = 'hist_update_hbuf' - character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)"] + character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)","mxgrowseas","mxharvests"] !----------------------------------------------------------------------- do t = 1,ntapes @@ -2279,7 +2279,7 @@ subroutine htape_create (t, histrest) ! ! !USES: use clm_varpar , only : nlevgrnd, nlevsno, nlevlak, nlevurb, nlevmaxurbgrnd, numrad, nlevcan, nvegwcs,nlevsoi - use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, nlevdecomp_full + use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, nlevdecomp_full, mxgrowseas, mxharvests use landunit_varcon , only : max_lunit use clm_varctl , only : caseid, ctitle, fsurdat, finidat, paramfile use clm_varctl , only : version, hostname, username, conventions, source @@ -2420,6 +2420,8 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'ltype', max_lunit, dimid) call ncd_defdim(lnfid, 'nlevcan',nlevcan, dimid) call ncd_defdim(lnfid, 'nvegwcs',nvegwcs, dimid) + call ncd_defdim(lnfid, 'mxgrowseas' , mxgrowseas , dimid) + call ncd_defdim(lnfid, 'mxharvests' , mxharvests , dimid) call htape_add_ltype_metadata(lnfid) call htape_add_ctype_metadata(lnfid) call ncd_defdim(lnfid, 'natpft', natpft_size, dimid) @@ -4142,7 +4144,7 @@ subroutine hist_restart_ncd (bounds, ncid, flag, rdate) use clm_varctl , only : nsrest, caseid, inst_suffix, nsrStartup, nsrBranch use fileutils , only : getfil use domainMod , only : ldomain - use clm_varpar , only : nlevgrnd, nlevlak, numrad, nlevdecomp_full + use clm_varpar , only : nlevgrnd, nlevlak, numrad, nlevdecomp_full, mxgrowseas, mxharvests use clm_time_manager, only : is_restart use restUtilMod , only : iflag_skip use pio @@ -5348,7 +5350,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, ! ! !USES: use clm_varpar , only : nlevgrnd, nlevsno, nlevlak, numrad, nlevdecomp_full, nlevcan, nvegwcs,nlevsoi - use clm_varpar , only : natpft_size, cft_size, maxpatch_glc + use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, mxgrowseas, mxharvests use landunit_varcon , only : max_lunit ! ! !ARGUMENTS: @@ -5428,6 +5430,10 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, num2d = numrad case ('levdcmp') num2d = nlevdecomp_full + case ('mxgrowseas') + num2d = mxgrowseas + case ('mxharvests') + num2d = mxharvests case ('fates_levscls') num2d = nlevsclass case('fates_levcacls') @@ -5497,7 +5503,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, case default write(iulog,*) trim(subname),' ERROR: unsupported 2d type ',type2d, & ' currently supported types for multi level fields are: ', & - '[levgrnd,levsoi,levlak,numrad,levdcmp,levtrc,ltype,natpft,cft,glc_nec,elevclas,levsno,nvegwcs]' + '[levgrnd,levsoi,levlak,numrad,levdcmp,levtrc,ltype,natpft,cft,glc_nec,elevclas,levsno,nvegwcs,mxgrowseas,mxharvests]' call endrun(msg=errMsg(sourcefile, __LINE__)) end select From 347215499f57c1d89adce32adf62e700d3087702 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 26 Jan 2022 16:03:36 -0700 Subject: [PATCH 03/21] Compile fix: Forgot to remove one line with an unused variable during cherry pick. --- src/biogeochem/CropType.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 3d8fccbc6b..c9bd1eb4f2 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -207,7 +207,6 @@ subroutine InitAllocate(this, bounds) allocate(this%sowing_count(begp:endp)) ; this%sowing_count(:) = 0 allocate(this%harvest_count(begp:endp)) ; this%harvest_count(:) = 0 - this%rx_sdates_thisyr(:,:) = -1 this%sdates_thisyr(:,:) = -1._r8 this%hdates_thisyr(:,:) = -1._r8 From b857d8c44001b00ce79e38d516a8998b31e84cea Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 27 Jan 2022 10:40:51 -0700 Subject: [PATCH 04/21] Use real() instead of DBLE(). Co-authored-by: Bill Sacks --- src/biogeochem/CNPhenologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index e6ab298a58..3f6b29c72b 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -2041,7 +2041,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday harvest_count(p) = harvest_count(p) + 1 - crop_inst%hdates_thisyr(p, harvest_count(p)) = DBLE(jday) + crop_inst%hdates_thisyr(p, harvest_count(p)) = real(jday, r8) croplive(p) = .false. ! no re-entry in greater if-block cphase(p) = 4._r8 if (tlai(p) > 0._r8) then ! plant had emerged before harvest From cc425897ac511191e2485a407e4c06fe47f21062 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 27 Jan 2022 12:32:14 -0700 Subject: [PATCH 05/21] Ensure that new variables are correctly set when resuming from a run with old code. --- src/biogeochem/CNPhenologyMod.F90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 3f6b29c72b..ce2a0edbca 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -1787,6 +1787,16 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & end do end if + ! Ensure that everything is correctly set when resuming from a run with old code + if (jday == 1 .and. croplive(p) .and. idop(p) == 1 .and. sowing_count(p) == 0) then + sowing_count(p) = 1 + crop_inst%sdates_thisyr(p,1) = 1._r8 + do s = 1, mxharvests + crop_inst%hdates_thisyr(p,s) = -1._r8 + end do + end if + + ! Once outputs can handle >1 planting per year, remove 2nd condition. if ( (.not. croplive(p)) .and. sowing_count(p) == 0 ) then From bc88cf9b0daed6bb2fdd4e973d6521b679c5ad3e Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 28 Jan 2022 13:26:57 -0700 Subject: [PATCH 06/21] REALLY ensure that new variables are correctly set when resuming from a run with old code. --- src/biogeochem/CNPhenologyMod.F90 | 8 +++----- src/biogeochem/CropType.F90 | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index ce2a0edbca..f9722f2343 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -1776,7 +1776,8 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! initialize other variables that are calculated for crops ! on an annual basis in cropresidue subroutine - if ( is_beg_curr_year() ) then + ! Second condition ensures everything is correctly set when resuming from a run with old code + if ( is_beg_curr_year() .or. crop_inst%sdates_thisyr(p,1) == spval ) then sowing_count(p) = 0 harvest_count(p) = 0 do s = 1, mxgrowseas @@ -1787,13 +1788,10 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & end do end if - ! Ensure that everything is correctly set when resuming from a run with old code + ! When resuming from a run with old code, may need to manually set these if (jday == 1 .and. croplive(p) .and. idop(p) == 1 .and. sowing_count(p) == 0) then sowing_count(p) = 1 crop_inst%sdates_thisyr(p,1) = 1._r8 - do s = 1, mxharvests - crop_inst%hdates_thisyr(p,s) = -1._r8 - end do end if diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index c9bd1eb4f2..3c399a9cdb 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -207,8 +207,8 @@ subroutine InitAllocate(this, bounds) allocate(this%sowing_count(begp:endp)) ; this%sowing_count(:) = 0 allocate(this%harvest_count(begp:endp)) ; this%harvest_count(:) = 0 - this%sdates_thisyr(:,:) = -1._r8 - this%hdates_thisyr(:,:) = -1._r8 + this%sdates_thisyr(:,:) = spval + this%hdates_thisyr(:,:) = spval end subroutine InitAllocate From 64911895be6b67af3153f1c39e4ac6df1cf3fce8 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Tue, 1 Feb 2022 16:57:22 -0700 Subject: [PATCH 07/21] Moved initialization of [sh]dates_thisyr to match convention. See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r796201072 --- src/biogeochem/CropType.F90 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 3c399a9cdb..4950b2227d 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -202,14 +202,11 @@ subroutine InitAllocate(this, bounds) allocate(this%vf_patch (begp:endp)) ; this%vf_patch (:) = 0.0_r8 allocate(this%cphase_patch (begp:endp)) ; this%cphase_patch (:) = 0.0_r8 allocate(this%latbaset_patch (begp:endp)) ; this%latbaset_patch (:) = spval - allocate(this%sdates_thisyr(begp:endp,1:mxgrowseas)) - allocate(this%hdates_thisyr(begp:endp,1:mxharvests)) + allocate(this%sdates_thisyr(begp:endp,1:mxgrowseas)) ; this%sdates_thisyr(:,:) = spval + allocate(this%hdates_thisyr(begp:endp,1:mxharvests)) ; this%hdates_thisyr(:,:) = spval allocate(this%sowing_count(begp:endp)) ; this%sowing_count(:) = 0 allocate(this%harvest_count(begp:endp)) ; this%harvest_count(:) = 0 - this%sdates_thisyr(:,:) = spval - this%hdates_thisyr(:,:) = spval - end subroutine InitAllocate !----------------------------------------------------------------------- From 86a09e0e28ceadcde55530e367ea893654d576ed Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Tue, 1 Feb 2022 17:03:12 -0700 Subject: [PATCH 08/21] Improved a comment. See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r796833890 --- src/biogeochem/CNPhenologyMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index f9722f2343..9556537cbe 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -1777,6 +1777,8 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! on an annual basis in cropresidue subroutine ! Second condition ensures everything is correctly set when resuming from a run with old code + ! OR starting a run mid-year without any restart file OR handling a new crop column that just + ! came into existence (and not at the year boundary for some reason). if ( is_beg_curr_year() .or. crop_inst%sdates_thisyr(p,1) == spval ) then sowing_count(p) = 0 harvest_count(p) = 0 From ac01b14a39540c830809ba7b4d1e4057f343bb8e Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 2 Feb 2022 16:39:19 -0700 Subject: [PATCH 09/21] CropType: Added [sh]dates_thisyr to restart files, with [sowing,harvest]_count derived from read-in values. --- src/biogeochem/CropType.F90 | 85 +++++++++++++++++++++++++++++++++++++ src/main/restFileMod.F90 | 3 ++ 2 files changed, 88 insertions(+) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 4950b2227d..bbe858e445 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -410,6 +410,41 @@ subroutine InitAccVars(this, bounds) end subroutine InitAccVars + !----------------------------------------------------------------------- + logical function CallRestartvarDimOK (ncid, flag, dimname) + ! + ! !DESCRIPTION: + ! Answer whether to call restartvar(), if necessary checking whether + ! a dimension exists in the restart file + ! + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) + ! Used in Restart(). Even though restartvar() can safely be called for a + ! non-existent variable, it gives an error for a non-existent dimension, so + ! check whether the dimension exists before trying to read. The need for this + ! function arose because we recently added the mxgrowseas and mxharvests + ! dimensions to the restart file. + ! + ! !USES: + use ncdio_pio + ! + ! !ARGUMENTS: + type(file_desc_t), intent(in) :: ncid + character(len=*) , intent(in) :: flag + character(len=*) , intent(in) :: dimname + ! + ! !LOCAL VARIABLES: + type(file_desc_t) :: ncid_local + !----------------------------------------------------------------------- + + ncid_local = ncid + if (flag == 'read') then + call check_var_or_dim(ncid_local, dimname, is_dim=.true., exists=CallRestartvarDimOK) + else + CallRestartvarDimOK = .true. + end if + + end function CallRestartvarDimOK + !----------------------------------------------------------------------- subroutine Restart(this, bounds, ncid, flag) ! @@ -418,6 +453,7 @@ subroutine Restart(this, bounds, ncid, flag) use ncdio_pio use PatchType, only : patch use pftconMod, only : npcropmin, npcropmax + use clm_varpar, only : mxgrowseas, mxharvests ! ! !ARGUMENTS: class(crop_type), intent(inout) :: this @@ -430,6 +466,7 @@ subroutine Restart(this, bounds, ncid, flag) integer :: restyear integer :: p logical :: readvar ! determine if variable is on initial file + integer :: c, d ! getting number of sowings/harvests in patch character(len=*), parameter :: subname = 'Restart' !----------------------------------------------------------------------- @@ -502,6 +539,54 @@ subroutine Restart(this, bounds, ncid, flag) ! This is so that it properly goes through ! the crop phases end if + + ! Read or write variable(s) with mxgrowseas dimension + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) See note in CallRestartvarDimOK() + if (CallRestartvarDimOK(ncid, flag, 'mxgrowseas')) then + call restartvar(ncid=ncid, flag=flag, varname='sdates_thisyr', xtype=ncd_double, & + dim1name='pft', dim2name='mxgrowseas', switchdim=.true., & + long_name='crop sowing dates for this patch this year', units='day of year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%sdates_thisyr) + ! Fill variable(s) derived from read-in variable(s) + if (flag == 'read' .and. readvar) then + do p = bounds%begp,bounds%endp + c = 0 + do d = 1,mxgrowseas + if (this%sdates_thisyr(p,d) >= 1 .and. this%sdates_thisyr(p,d) <= 366) then + c = d + else + exit + end if + end do ! loop through possible sowings + this%sowing_count(p) = c + end do ! loop through patches + end if + end if + + ! Read or write variable(s) with mxharvests dimension + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) See note in CallRestartvarDimOK() + if (CallRestartvarDimOK(ncid, flag, 'mxharvests')) then + call restartvar(ncid=ncid, flag=flag, varname='hdates_thisyr', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='crop harvest dates for this patch this year', units='day of year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%hdates_thisyr) + ! Fill variable(s) derived from read-in variable(s) + if (flag == 'read' .and. readvar) then + do p = bounds%begp,bounds%endp + c = 0 + do d = 1,mxharvests + if (this%hdates_thisyr(p,d) >= 1 .and. this%hdates_thisyr(p,d) <= 366) then + c = d + else + exit + end if + end do ! loop through possible harvests + this%harvest_count(p) = c + end do ! loop through patches + end if + end if end if end subroutine Restart diff --git a/src/main/restFileMod.F90 b/src/main/restFileMod.F90 index f0b2b4fb01..b54c6a1eaa 100644 --- a/src/main/restFileMod.F90 +++ b/src/main/restFileMod.F90 @@ -507,6 +507,7 @@ subroutine restFile_dimset( ncid ) use dynSubgridControlMod , only : get_flanduse_timeseries use clm_varpar , only : numrad, nlevlak, nlevsno, nlevgrnd, nlevmaxurbgrnd, nlevcan use clm_varpar , only : maxpatch_glc, nvegwcs + use clm_varpar , only : mxgrowseas, mxharvests use decompMod , only : get_proc_global ! ! !ARGUMENTS: @@ -545,6 +546,8 @@ subroutine restFile_dimset( ncid ) call ncd_defdim(ncid , 'levtot' , nlevsno+nlevmaxurbgrnd, dimid) call ncd_defdim(ncid , 'numrad' , numrad , dimid) call ncd_defdim(ncid , 'levcan' , nlevcan , dimid) + call ncd_defdim(ncid , 'mxgrowseas' , mxgrowseas , dimid) + call ncd_defdim(ncid , 'mxharvests' , mxharvests , dimid) if ( use_hydrstress ) then call ncd_defdim(ncid , 'vegwcs' , nvegwcs , dimid) end if From d1ca586bf1f95345f8899ee5415a07542c5880af Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 4 Feb 2022 11:38:14 -0700 Subject: [PATCH 10/21] ncid now inout in CallRestartvarDimOK(). See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r798888500 --- src/biogeochem/CropType.F90 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index bbe858e445..c86b272c6a 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -428,17 +428,15 @@ logical function CallRestartvarDimOK (ncid, flag, dimname) use ncdio_pio ! ! !ARGUMENTS: - type(file_desc_t), intent(in) :: ncid + type(file_desc_t), intent(inout) :: ncid character(len=*) , intent(in) :: flag character(len=*) , intent(in) :: dimname ! ! !LOCAL VARIABLES: - type(file_desc_t) :: ncid_local !----------------------------------------------------------------------- - ncid_local = ncid if (flag == 'read') then - call check_var_or_dim(ncid_local, dimname, is_dim=.true., exists=CallRestartvarDimOK) + call check_var_or_dim(ncid, dimname, is_dim=.true., exists=CallRestartvarDimOK) else CallRestartvarDimOK = .true. end if From 7601ec88fe409484962693e136e0786379aa6f1d Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 4 Feb 2022 11:40:13 -0700 Subject: [PATCH 11/21] More descriptive variable names. See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r798888500 --- src/biogeochem/CropType.F90 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index c86b272c6a..fb7f26fee3 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -464,7 +464,7 @@ subroutine Restart(this, bounds, ncid, flag) integer :: restyear integer :: p logical :: readvar ! determine if variable is on initial file - integer :: c, d ! getting number of sowings/harvests in patch + integer :: seasons_found, seasons_loopvar ! getting number of sowings/harvests in patch character(len=*), parameter :: subname = 'Restart' !----------------------------------------------------------------------- @@ -549,15 +549,15 @@ subroutine Restart(this, bounds, ncid, flag) ! Fill variable(s) derived from read-in variable(s) if (flag == 'read' .and. readvar) then do p = bounds%begp,bounds%endp - c = 0 - do d = 1,mxgrowseas - if (this%sdates_thisyr(p,d) >= 1 .and. this%sdates_thisyr(p,d) <= 366) then - c = d + seasons_found = 0 + do seasons_loopvar = 1,mxgrowseas + if (this%sdates_thisyr(p,seasons_loopvar) >= 1 .and. this%sdates_thisyr(p,seasons_loopvar) <= 366) then + seasons_found = seasons_loopvar else exit end if end do ! loop through possible sowings - this%sowing_count(p) = c + this%sowing_count(p) = seasons_found end do ! loop through patches end if end if @@ -573,15 +573,15 @@ subroutine Restart(this, bounds, ncid, flag) ! Fill variable(s) derived from read-in variable(s) if (flag == 'read' .and. readvar) then do p = bounds%begp,bounds%endp - c = 0 - do d = 1,mxharvests - if (this%hdates_thisyr(p,d) >= 1 .and. this%hdates_thisyr(p,d) <= 366) then - c = d + seasons_found = 0 + do seasons_loopvar = 1,mxharvests + if (this%hdates_thisyr(p,seasons_loopvar) >= 1 .and. this%hdates_thisyr(p,seasons_loopvar) <= 366) then + seasons_found = seasons_loopvar else exit end if end do ! loop through possible harvests - this%harvest_count(p) = c + this%harvest_count(p) = seasons_found end do ! loop through patches end if end if From 948bcc9b22233d814068e78fcf9e3444d9168c2b Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 4 Feb 2022 11:48:26 -0700 Subject: [PATCH 12/21] CallRestartvarDimOK now uses check_dim() instead of check_var_or_dim(). See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r798888500 --- src/biogeochem/CropType.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index fb7f26fee3..c39ecb041e 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -436,7 +436,7 @@ logical function CallRestartvarDimOK (ncid, flag, dimname) !----------------------------------------------------------------------- if (flag == 'read') then - call check_var_or_dim(ncid, dimname, is_dim=.true., exists=CallRestartvarDimOK) + call check_dim(ncid, dimname, dimexist=CallRestartvarDimOK) else CallRestartvarDimOK = .true. end if From b878b33feab429c426ed54212ee15eb514b7b87f Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 28 Oct 2021 11:06:40 -0600 Subject: [PATCH 13/21] Git now ignores .vscode/. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 1c9f52fe14..2ecdfb262e 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,6 @@ core.* *.log !run.log *.pyc Depends + +# ssr +.vscode/ From b89ea277dea35341f52c88986df917123e0324fb Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 4 Feb 2022 15:39:41 -0700 Subject: [PATCH 14/21] Minor .gitignore rearrange. --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2ecdfb262e..a953d2aadd 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ manage_externals.log # editor files *.swp *~ +.vscode/ # vim files (from https://github.com/github/gitignore/blob/master/Global/Vim.gitignore) # Swap @@ -112,6 +113,3 @@ core.* *.log !run.log *.pyc Depends - -# ssr -.vscode/ From 7a2c8166f0c45afdc3685f702b4a501fdb67be0a Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 14 Feb 2022 16:03:52 -0700 Subject: [PATCH 15/21] Renamed mxgrowseas to mxsowings; added explanatory comment on mxharvests definition. See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r801163127 --- src/biogeochem/CNPhenologyMod.F90 | 4 ++-- src/biogeochem/CropType.F90 | 18 +++++++++--------- src/main/clm_varpar.F90 | 8 +++++--- src/main/histFileMod.F90 | 18 +++++++++--------- src/main/restFileMod.F90 | 4 ++-- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 5d93513346..25b3513d5a 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -14,7 +14,7 @@ module CNPhenologyMod use shr_log_mod , only : errMsg => shr_log_errMsg use shr_sys_mod , only : shr_sys_flush use decompMod , only : bounds_type - use clm_varpar , only : maxveg, nlevdecomp_full, mxgrowseas, mxharvests + use clm_varpar , only : maxveg, nlevdecomp_full, mxsowings, mxharvests use clm_varpar , only : i_litr_min, i_litr_max use clm_varctl , only : iulog, use_cndv use clm_varcon , only : tfrz @@ -1798,7 +1798,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & if ( is_beg_curr_year() .or. crop_inst%sdates_thisyr(p,1) == spval ) then sowing_count(p) = 0 harvest_count(p) = 0 - do s = 1, mxgrowseas + do s = 1, mxsowings crop_inst%sdates_thisyr(p,s) = -1._r8 end do do s = 1, mxharvests diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index c39ecb041e..efc919a21c 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -179,7 +179,7 @@ end subroutine ReadNML subroutine InitAllocate(this, bounds) ! !USES: ! - use clm_varpar, only : mxgrowseas, mxharvests + use clm_varpar, only : mxsowings, mxharvests ! ! !ARGUMENTS: class(crop_type) , intent(inout) :: this @@ -202,7 +202,7 @@ subroutine InitAllocate(this, bounds) allocate(this%vf_patch (begp:endp)) ; this%vf_patch (:) = 0.0_r8 allocate(this%cphase_patch (begp:endp)) ; this%cphase_patch (:) = 0.0_r8 allocate(this%latbaset_patch (begp:endp)) ; this%latbaset_patch (:) = spval - allocate(this%sdates_thisyr(begp:endp,1:mxgrowseas)) ; this%sdates_thisyr(:,:) = spval + allocate(this%sdates_thisyr(begp:endp,1:mxsowings)) ; this%sdates_thisyr(:,:) = spval allocate(this%hdates_thisyr(begp:endp,1:mxharvests)) ; this%hdates_thisyr(:,:) = spval allocate(this%sowing_count(begp:endp)) ; this%sowing_count(:) = 0 allocate(this%harvest_count(begp:endp)) ; this%harvest_count(:) = 0 @@ -255,7 +255,7 @@ subroutine InitHistory(this, bounds) end if this%sdates_thisyr(begp:endp,:) = spval - call hist_addfld2d (fname='SDATES', units='day of year', type2d='mxgrowseas', & + call hist_addfld2d (fname='SDATES', units='day of year', type2d='mxsowings', & avgflag='I', long_name='actual crop sowing dates; should only be output annually', & ptr_patch=this%sdates_thisyr, default='inactive') @@ -421,7 +421,7 @@ logical function CallRestartvarDimOK (ncid, flag, dimname) ! Used in Restart(). Even though restartvar() can safely be called for a ! non-existent variable, it gives an error for a non-existent dimension, so ! check whether the dimension exists before trying to read. The need for this - ! function arose because we recently added the mxgrowseas and mxharvests + ! function arose because we recently added the mxsowings and mxharvests ! dimensions to the restart file. ! ! !USES: @@ -451,7 +451,7 @@ subroutine Restart(this, bounds, ncid, flag) use ncdio_pio use PatchType, only : patch use pftconMod, only : npcropmin, npcropmax - use clm_varpar, only : mxgrowseas, mxharvests + use clm_varpar, only : mxsowings, mxharvests ! ! !ARGUMENTS: class(crop_type), intent(inout) :: this @@ -538,11 +538,11 @@ subroutine Restart(this, bounds, ncid, flag) ! the crop phases end if - ! Read or write variable(s) with mxgrowseas dimension + ! Read or write variable(s) with mxsowings dimension ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) See note in CallRestartvarDimOK() - if (CallRestartvarDimOK(ncid, flag, 'mxgrowseas')) then + if (CallRestartvarDimOK(ncid, flag, 'mxsowings')) then call restartvar(ncid=ncid, flag=flag, varname='sdates_thisyr', xtype=ncd_double, & - dim1name='pft', dim2name='mxgrowseas', switchdim=.true., & + dim1name='pft', dim2name='mxsowings', switchdim=.true., & long_name='crop sowing dates for this patch this year', units='day of year', & scale_by_thickness=.false., & interpinic_flag='interp', readvar=readvar, data=this%sdates_thisyr) @@ -550,7 +550,7 @@ subroutine Restart(this, bounds, ncid, flag) if (flag == 'read' .and. readvar) then do p = bounds%begp,bounds%endp seasons_found = 0 - do seasons_loopvar = 1,mxgrowseas + do seasons_loopvar = 1,mxsowings if (this%sdates_thisyr(p,seasons_loopvar) >= 1 .and. this%sdates_thisyr(p,seasons_loopvar) <= 366) then seasons_found = seasons_loopvar else diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index e47de8854b..e5d296bb52 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -51,8 +51,10 @@ module clm_varpar integer, public, parameter :: dst_src_nbr = 3 ! number of size distns in src soil (BGC only) integer, public, parameter :: sz_nbr = 200 ! number of sub-grid bins in large bin of dust size distribution (BGC only) integer, public, parameter :: mxpft = 78 ! maximum number of PFT's for any mode; - integer, public, parameter :: mxgrowseas = 1 ! maximum number of crop growing seasons to begin in any year; - integer, public :: mxharvests ! maximum number of crop harvests in any year; + integer, public, parameter :: mxsowings = 1 ! maximum number of crop growing seasons to begin in any year; + integer, public :: mxharvests ! maximum number of crop harvests in any year + ! (allows for multiple harvests in a calendar year in case harvest occurs near + ! beginning/end of year); ! FIX(RF,032414) might we set some of these automatically from reading pft-physiology? integer, public, parameter :: nlayer = 3 ! number of VIC soil layer --Added by AWang integer, public :: nlayert ! number of VIC soil layer + 3 lower thermal layers @@ -147,7 +149,7 @@ subroutine clm_varpar_init(actual_maxsoil_patches, actual_numcft) cft_lb = natpft_ub + 1 cft_ub = cft_lb + cft_size - 1 - mxharvests = mxgrowseas + 1 + mxharvests = mxsowings + 1 ! TODO(wjs, 2015-10-04, bugz 2227) Using actual_numcft in this 'max' gives a significant ! overestimate of max_patch_per_col when use_crop is true. This should be reworked - diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index 68acbe12c6..5224f44ae2 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -193,7 +193,7 @@ module histFileMod character(len=max_chars) :: units ! units character(len=hist_dim_name_length) :: type1d ! pointer to first dimension type from data type (nameg, etc) character(len=hist_dim_name_length) :: type1d_out ! hbuf first dimension type from data type (nameg, etc) - character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)","mxgrowseas","mxharvests"] + character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)","mxsowings","mxharvests"] integer :: beg1d ! on-node 1d clm pointer start index integer :: end1d ! on-node 1d clm pointer end index integer :: num1d ! size of clm pointer first dimension (all nodes) @@ -1271,7 +1271,7 @@ subroutine hist_update_hbuf(bounds) integer :: num2d ! size of second dimension (e.g. number of vertical levels) integer :: numdims ! number of dimensions character(len=*),parameter :: subname = 'hist_update_hbuf' - character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)","mxgrowseas","mxharvests"] + character(len=hist_dim_name_length) :: type2d ! hbuf second dimension type ["levgrnd","levlak","numrad","ltype","natpft","cft","glc_nec","elevclas","subname(n)","mxsowings","mxharvests"] !----------------------------------------------------------------------- do t = 1,ntapes @@ -2279,7 +2279,7 @@ subroutine htape_create (t, histrest) ! ! !USES: use clm_varpar , only : nlevgrnd, nlevsno, nlevlak, nlevurb, nlevmaxurbgrnd, numrad, nlevcan, nvegwcs,nlevsoi - use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, nlevdecomp_full, mxgrowseas, mxharvests + use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, nlevdecomp_full, mxsowings, mxharvests use landunit_varcon , only : max_lunit use clm_varctl , only : caseid, ctitle, fsurdat, finidat, paramfile use clm_varctl , only : version, hostname, username, conventions, source @@ -2420,7 +2420,7 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'ltype', max_lunit, dimid) call ncd_defdim(lnfid, 'nlevcan',nlevcan, dimid) call ncd_defdim(lnfid, 'nvegwcs',nvegwcs, dimid) - call ncd_defdim(lnfid, 'mxgrowseas' , mxgrowseas , dimid) + call ncd_defdim(lnfid, 'mxsowings' , mxsowings , dimid) call ncd_defdim(lnfid, 'mxharvests' , mxharvests , dimid) call htape_add_ltype_metadata(lnfid) call htape_add_ctype_metadata(lnfid) @@ -4144,7 +4144,7 @@ subroutine hist_restart_ncd (bounds, ncid, flag, rdate) use clm_varctl , only : nsrest, caseid, inst_suffix, nsrStartup, nsrBranch use fileutils , only : getfil use domainMod , only : ldomain - use clm_varpar , only : nlevgrnd, nlevlak, numrad, nlevdecomp_full, mxgrowseas, mxharvests + use clm_varpar , only : nlevgrnd, nlevlak, numrad, nlevdecomp_full, mxsowings, mxharvests use clm_time_manager, only : is_restart use restUtilMod , only : iflag_skip use pio @@ -5350,7 +5350,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, ! ! !USES: use clm_varpar , only : nlevgrnd, nlevsno, nlevlak, numrad, nlevdecomp_full, nlevcan, nvegwcs,nlevsoi - use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, mxgrowseas, mxharvests + use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, mxsowings, mxharvests use landunit_varcon , only : max_lunit ! ! !ARGUMENTS: @@ -5430,8 +5430,8 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, num2d = numrad case ('levdcmp') num2d = nlevdecomp_full - case ('mxgrowseas') - num2d = mxgrowseas + case ('mxsowings') + num2d = mxsowings case ('mxharvests') num2d = mxharvests case ('fates_levscls') @@ -5503,7 +5503,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, case default write(iulog,*) trim(subname),' ERROR: unsupported 2d type ',type2d, & ' currently supported types for multi level fields are: ', & - '[levgrnd,levsoi,levlak,numrad,levdcmp,levtrc,ltype,natpft,cft,glc_nec,elevclas,levsno,nvegwcs,mxgrowseas,mxharvests]' + '[levgrnd,levsoi,levlak,numrad,levdcmp,levtrc,ltype,natpft,cft,glc_nec,elevclas,levsno,nvegwcs,mxsowings,mxharvests]' call endrun(msg=errMsg(sourcefile, __LINE__)) end select diff --git a/src/main/restFileMod.F90 b/src/main/restFileMod.F90 index b54c6a1eaa..f953419360 100644 --- a/src/main/restFileMod.F90 +++ b/src/main/restFileMod.F90 @@ -507,7 +507,7 @@ subroutine restFile_dimset( ncid ) use dynSubgridControlMod , only : get_flanduse_timeseries use clm_varpar , only : numrad, nlevlak, nlevsno, nlevgrnd, nlevmaxurbgrnd, nlevcan use clm_varpar , only : maxpatch_glc, nvegwcs - use clm_varpar , only : mxgrowseas, mxharvests + use clm_varpar , only : mxsowings, mxharvests use decompMod , only : get_proc_global ! ! !ARGUMENTS: @@ -546,7 +546,7 @@ subroutine restFile_dimset( ncid ) call ncd_defdim(ncid , 'levtot' , nlevsno+nlevmaxurbgrnd, dimid) call ncd_defdim(ncid , 'numrad' , numrad , dimid) call ncd_defdim(ncid , 'levcan' , nlevcan , dimid) - call ncd_defdim(ncid , 'mxgrowseas' , mxgrowseas , dimid) + call ncd_defdim(ncid , 'mxsowings' , mxsowings , dimid) call ncd_defdim(ncid , 'mxharvests' , mxharvests , dimid) if ( use_hydrstress ) then call ncd_defdim(ncid , 'vegwcs' , nvegwcs , dimid) From ca90b780c5e8b2eab818d3addd5950bb338c6f64 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 18 Feb 2022 09:34:18 -0700 Subject: [PATCH 16/21] Elaboration of a comment related to backwards compatibility. See https://github.com/ESCOMP/CTSM/pull/1616#discussion_r797748751 --- src/biogeochem/CNPhenologyMod.F90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 09f1a5d9cc..ff7a7e21a0 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -1804,7 +1804,12 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & end do end if - ! When resuming from a run with old code, may need to manually set these + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-18) + ! When resuming from a run with old code, may need to manually set these. + ! Will be needed until we can rely on all restart files have been generated + ! with CropPhenology() getting the day of the year from the START of the timestep + ! (i.e., jday = get_prev_calday()) instead of the END of the timestep (i.e., + ! jday = get_calday()). See CTSM issue #1623. if (jday == 1 .and. croplive(p) .and. idop(p) == 1 .and. sowing_count(p) == 0) then sowing_count(p) = 1 crop_inst%sdates_thisyr(p,1) = 1._r8 From 851764603a85d92e17048099c8f4879dd56d13ff Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Mar 2022 15:49:15 -0700 Subject: [PATCH 17/21] Generalized backwards compatibility setting of sowing_count and sdates_thisyear to work when resuming on days other than Jan. 1. --- src/biogeochem/CNPhenologyMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index ff7a7e21a0..0ff1631eac 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -1810,9 +1810,9 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! with CropPhenology() getting the day of the year from the START of the timestep ! (i.e., jday = get_prev_calday()) instead of the END of the timestep (i.e., ! jday = get_calday()). See CTSM issue #1623. - if (jday == 1 .and. croplive(p) .and. idop(p) == 1 .and. sowing_count(p) == 0) then + if (croplive(p) .and. idop(p) <= jday .and. sowing_count(p) == 0) then sowing_count(p) = 1 - crop_inst%sdates_thisyr(p,1) = 1._r8 + crop_inst%sdates_thisyr(p,1) = real(idop(p), r8) end if From 3aa7d651efb37653b47375bf51d8b9c48ce1bbf9 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 11 Mar 2022 16:06:14 -0700 Subject: [PATCH 18/21] Now sets rootdepth for crops to 0 outside growing season. See https://github.com/ESCOMP/CTSM/pull/1616#issuecomment-1061213667 --- src/biogeochem/CNRootDynMod.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/biogeochem/CNRootDynMod.F90 b/src/biogeochem/CNRootDynMod.F90 index 4d34d54f7c..d6f8bcd3e7 100644 --- a/src/biogeochem/CNRootDynMod.F90 +++ b/src/biogeochem/CNRootDynMod.F90 @@ -135,7 +135,9 @@ subroutine CNRootDyn(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & c = pcolumn(p) if (ivt(p) /= noveg) then if((ivt(p)) >= npcropmin)then !skip generic crop types - if(huigrain(p) > 0._r8)then + if (.not. croplive(p)) then + root_depth(p) = 0._r8 + else if(huigrain(p) > 0._r8)then root_depth(p) = max(zi(c,2), min(hui(p)/huigrain(p)* root_dmx(ivt(p)), root_dmx(ivt(p)))) end if else From 0c67c804f74ede650231d03ad2c75dd042fac681 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 24 Mar 2022 14:36:57 -0600 Subject: [PATCH 19/21] Add new crop history variables to some tests --- .../testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm index b2a51bd5d5..a1165352fe 100644 --- a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm @@ -1,2 +1,5 @@ - hist_nhtfrq = 0,-240 - hist_mfilt = 1,1 + hist_nhtfrq = 0,-240,-8760 + hist_mfilt = 1,1,1 + + ! Add an annual output file with these crop-specific variables, which exercise some special logic: + hist_fincl3 = 'SDATES', 'HDATES' From 5de54d1a0a5730ce825c81c6b51db90bcc3c97f6 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 25 Mar 2022 16:21:25 -0600 Subject: [PATCH 20/21] Fix unit test build To test this on my mac, I needed to cherry-pick in two of my recent cime commits: ESMCI/cime@4d202f64b and ESMCI/cime@240ff4c37 (from https://github.com/ESMCI/cime/pull/4203 and https://github.com/ESMCI/cime/pull/4205 ). --- src/README.unit_testing | 2 +- .../main/ncdio_pio_fake.F90.in | 25 ++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/README.unit_testing b/src/README.unit_testing index aaaa0038ff..897e7869ce 100644 --- a/src/README.unit_testing +++ b/src/README.unit_testing @@ -5,7 +5,7 @@ # time you ran them from this directory. # From a standalone CTSM checkout: -CIME_NO_CMAKE_MACRO=ON ../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp +../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp # If you are within a full CESM checkout, you would instead do: # ../../../cime/scripts/fortran_unit_testing/run_tests.py --build-dir unit_tests.temp diff --git a/src/unit_test_stubs/main/ncdio_pio_fake.F90.in b/src/unit_test_stubs/main/ncdio_pio_fake.F90.in index c6bfa436b6..e8ef14e457 100644 --- a/src/unit_test_stubs/main/ncdio_pio_fake.F90.in +++ b/src/unit_test_stubs/main/ncdio_pio_fake.F90.in @@ -46,6 +46,7 @@ module ncdio_pio ! !PUBLIC MEMBER FUNCTIONS: public :: check_var ! determine if variable is on netcdf file + public :: check_dim ! determine if dimension is on netcdf file public :: check_var_or_dim ! determine if variable or dimension is on netcdf file public :: ncd_io ! do fake i/o (currently only set up to read) public :: ncd_inqvid ! inquire on a variable id @@ -294,14 +295,32 @@ contains end subroutine check_var + !----------------------------------------------------------------------- + subroutine check_dim(ncid, dimname, dimexist) + ! + ! Fake to check if dimension is on netcdf file + ! + ! !ARGUMENTS: + class(file_desc_t) , intent(inout) :: ncid ! PIO file descriptor + character(len=*) , intent(in) :: dimname ! dimension name + logical , intent(out) :: dimexist ! if this dimension exists or not + ! + ! !LOCAL VARIABLES: + integer :: dimid + + character(len=*), parameter :: subname = 'check_dim' + !----------------------------------------------------------------------- + + call ncd_inqdid(ncid, dimname, dimid, dimexist) + + end subroutine check_dim + !----------------------------------------------------------------------- subroutine check_var_or_dim(ncid, name, is_dim, exists) ! ! !DESCRIPTION: ! Fake to check if variable or dimension is on netcdf file ! - ! NOTE: dimension check currently not implemented! - ! ! !ARGUMENTS: class(file_desc_t) , intent(inout) :: ncid ! PIO file descriptor character(len=*) , intent(in) :: name ! variable or dimension name to check @@ -314,7 +333,7 @@ contains !----------------------------------------------------------------------- if (is_dim) then - call shr_sys_abort(subname//': is_dim=.true. not yet implemented') + call check_dim(ncid, name, exists) else call check_var(ncid, name, exists, print_err=.false.) end if From c50409af31f996cda1ed9568ff5ffe4b2070cc3a Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 25 Mar 2022 20:50:33 -0600 Subject: [PATCH 21/21] In cropMonthOutput testmod, change the new hist file to be vector Vector format makes more sense for these SDATES and HDATES fields --- .../testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm | 1 + 1 file changed, 1 insertion(+) diff --git a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm index a1165352fe..dfe718a7b4 100644 --- a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm @@ -3,3 +3,4 @@ ! Add an annual output file with these crop-specific variables, which exercise some special logic: hist_fincl3 = 'SDATES', 'HDATES' + hist_dov2xy(3) = .false.