diff --git a/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm index dc22a973b2..8e5a42fa50 100644 --- a/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm @@ -15,3 +15,5 @@ hist_nhtfrq(3) = 17520 hist_mfilt(3) = 1 hist_type1d_pertape(3) = 'PFTS' hist_dov2xy(3) = .false. +hist_avgflag_pertape(3) = 'I' + diff --git a/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm index 6dc5225f1d..4e5d38a444 100644 --- a/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm @@ -1,6 +1,6 @@ calc_human_stress_indices = 'ALL' hist_master_list_file = .true. -hist_fincl1 += 'GSSUN:L43200', 'GSSHA:L43200', 'FSDSND:L43200', 'FSRND:L43200', 'FSRSFND:L43200', - 'SSRE_FSRND:L43200', 'FSDSVD:L43200', 'FSDSVI:L43200', - 'FSRVD:L43200', 'FSRSFVD:L43200', 'SSRE_FSRVD:L43200' +hist_fincl3 = 'GSSUN', 'GSSHA', 'FSDSND', 'FSRND', 'FSRSFND', 'SSRE_FSRND', + 'FSDSVD', 'FSDSVI', 'FSRVD', 'FSRSFVD', 'SSRE_FSRVD' +hist_avgflag_pertape(3) = 'L43200' diff --git a/cime_config/usermods_dirs/_includes/output_base_highfreq/user_nl_clm b/cime_config/usermods_dirs/_includes/output_base_highfreq/user_nl_clm index 0e1ceeb4a5..ea19bb829e 100644 --- a/cime_config/usermods_dirs/_includes/output_base_highfreq/user_nl_clm +++ b/cime_config/usermods_dirs/_includes/output_base_highfreq/user_nl_clm @@ -20,11 +20,21 @@ hist_fincl7 += 'TREFMXAV','TREFMNAV' ! h7 stream (3-hourly average, gridcell-level) ! 3hr, E3hr, CF3hr -! 3hr requires QRUNOFF for time mean, and SOILWATER_10CM, TSKIN for time point (I) -! CF3hr requires QFLX_SOLIDEVAP_FROM_TOP_LAYER for time point (I) +! 3hr requires QRUNOFF for time mean hist_mfilt(8) = 2920 hist_dov2xy(8) = .true. hist_nhtfrq(8) = -3 hist_type1d_pertape(8) = ' ' -hist_fincl8 += 'TSA','RH2M','SOILWATER_10CM:I','FSH','EFLX_LH_TOT','FSDS','QRUNOFF','QFLX_SOLIDEVAP_FROM_TOP_LAYER:I','TSKIN:I' +hist_fincl8 += 'TSA','RH2M','FSH','EFLX_LH_TOT','FSDS','QRUNOFF' + +! h8 stream (3-hourly average, gridcell-level) +! 3hr, E3hr, CF3hr +! 3hr requires SOILWATER_10CM, TSKIN for time point (I) +! CF3hr requires QFLX_SOLIDEVAP_FROM_TOP_LAYER for time point (I) +hist_mfilt(9) = 2920 +hist_dov2xy(9) = .true. +hist_nhtfrq(9) = -3 +hist_type1d_pertape(9) = ' ' +hist_avgflag_pertape(9) = 'I' +hist_fincl9 += 'SOILWATER_10CM','QFLX_SOLIDEVAP_FROM_TOP_LAYER','TSKIN' diff --git a/cime_config/usermods_dirs/output_bgc/user_nl_clm b/cime_config/usermods_dirs/output_bgc/user_nl_clm index f7aaa09911..ea28beaf3b 100644 --- a/cime_config/usermods_dirs/output_bgc/user_nl_clm +++ b/cime_config/usermods_dirs/output_bgc/user_nl_clm @@ -11,11 +11,11 @@ hist_fincl2 += 'GPP', 'NPP', 'AGNPP', 'TOTVEGC', 'NPP_NUPTAKE', 'AR', 'HR', 'HTO ! h2 stream (monthly average, landunit-level) ! TOT_WOODPRODC:I, CROPPROD1C:I, and NEE are not available at the landunit level -hist_fincl3 += 'GPP', 'NPP', 'AR', 'HR', 'DWT_CONV_CFLUX_PATCH', 'WOOD_HARVESTC', 'DWT_WOOD_PRODUCTC_GAIN_PATCH', 'SLASH_HARVESTC', 'COL_FIRE_CLOSS', 'FROOTC:I', 'HTOP' +hist_fincl3 += 'GPP', 'NPP', 'AR', 'HR', 'DWT_CONV_CFLUX_PATCH', 'WOOD_HARVESTC', 'DWT_WOOD_PRODUCTC_GAIN_PATCH', 'SLASH_HARVESTC', 'COL_FIRE_CLOSS', 'HTOP' ! h3 stream (yearly average, gridcell-level) -hist_fincl4 += 'SOILC_vr', 'SOILN_vr', 'CWDC_vr', 'MET_LITC_vr', 'CEL_LITC_vr', 'LIG_LITC_vr', 'MET_LITN_vr', 'CEL_LITN_vr', 'LIG_LITN_vr','CWDN_vr', 'TOTLITC:I', 'TOT_WOODPRODC:I', 'TOTSOMC:I','TOTVEGC:I' +hist_fincl4 += 'SOILC_vr', 'SOILN_vr', 'CWDC_vr', 'MET_LITC_vr', 'CEL_LITC_vr', 'LIG_LITC_vr', 'MET_LITN_vr', 'CEL_LITN_vr', 'LIG_LITN_vr','CWDN_vr' ! h4 stream (yearly average, landunit-level) -hist_fincl5 += 'TOTSOMC:I', 'TOTSOMC_1m:I', 'TOTECOSYSC:I', 'TOTVEGC:I', 'WOODC:I', 'TOTLITC:I', 'LIVECROOTC:I', 'DEADCROOTC:I', 'FROOTC:I' - +hist_fincl5 += 'TOTSOMC', 'TOTSOMC_1m', 'TOTECOSYSC', 'TOTVEGC', 'WOODC', 'TOTLITC', 'LIVECROOTC', 'DEADCROOTC', 'FROOTC' +hist_avgflag_pertape(5) = 'I' diff --git a/cime_config/usermods_dirs/output_crop/user_nl_clm b/cime_config/usermods_dirs/output_crop/user_nl_clm index 638fea8815..92c351f07c 100644 --- a/cime_config/usermods_dirs/output_crop/user_nl_clm +++ b/cime_config/usermods_dirs/output_crop/user_nl_clm @@ -12,5 +12,5 @@ hist_fincl2 += 'GRAINC_TO_FOOD','NFERTILIZATION' hist_fincl3 += 'GRAINC_TO_FOOD' ! h3 stream (yearly average, gridcell-level) -hist_fincl4 += 'PCT_CFT','CROPPROD1C:I' +hist_fincl4 += 'PCT_CFT' diff --git a/doc/ChangeLog b/doc/ChangeLog index e65560d5c3..fa6c85df66 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,126 @@ =============================================================== +Tag name: ctsm5.1.dev13? +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri Aug 11 16:18:08 MDT 2023 +One-line Summary: Change history time var and put 'I' fields on separate hist file + +Purpose and description of changes +---------------------------------- + + These changes make CTSM output consistent with CMIP. + Of course we will maintain consistency across CESM components, as well. + We have + - redefined our history time variable from "end of time_bounds" to + "middle of time_bounds" for all fields except instantaneous ('I') + - moved 'I' fields to their own separate history files because + their time variable is defined as "end of time_bounds" + - removed time_bounds from 'I' history tapes + - moved 'L' fields to their own separate history files because they represent + a local time within the time_bounds + - clarified the long_name for several history time variables + + I made respective updates in ESCOMP/RTM#32 and ESCOMP/MOSART#52, as well. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): + Fixes #1059 + + +Notes of particular relevance for users +--------------------------------------- +Caveats for users (e.g., need to interpolate initial conditions): + Changes to history time-related variables as explained above. + + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + + +Testing summary: +---------------- +[Remove any lines that don't apply.] + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - + + tools-tests (test/tools) (if tools have been changed): + + cheyenne - + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + (any machine) - + + [If python code has changed and you are NOT running aux_clm (e.g., because the only changes are in python + code) then also run the clm_pymods test suite; this is a small subset of aux_clm that runs the system + tests impacted by python changes. The best way to do this, if you expect no changes from the last tag in + either model output or namelists, is: create sym links pointing to the last tag's baseline directory, + named with the upcoming tag; then run the clm_pymods test suite comparing against these baselines but NOT + doing their own baseline generation. If you are already running the full aux_clm then you do NOT need to + separately run the clm_pymods test suite, and you can remove the following line.] + + clm_pymods test suite on cheyenne - + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- + izumi ------- + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- + izumi ------- + + any other testing (give details below): + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: + Yes, for time-related variables only. + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: All + - nature of change: Time-related variables have changed as explained above. + Otherwise bit-for-bit. + + I ran the LMWG diagnostics package at @billsacks recommendation and + confirmed that all results look identical despite the changes to time-related + variables. + + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2019 + +=============================================================== +=============================================================== Tag name: ctsm5.1.dev133 Originator(s): adrifoster (Adrianna Foster), glemieux (Gregory Lemieux, LBL/NGEET) Date: Wed Aug 9 22:44:46 MDT 2023 diff --git a/doc/ChangeSum b/doc/ChangeSum index a72e6235ae..1664de1dad 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.1.dev13? slevis ??/??/2023 Change history time var and put 'I' fields on separate hist file ctsm5.1.dev133 glemieux 08/09/2023 FATES API update to facilitate fates refactor ctsm5.1.dev132 slevis 08/04/2023 Add parameterization to allow excess ice in soil and subsidence ctsm5.1.dev131 samrabin 07/27/2023 Enable prescribed crop calendars diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index c2025fca47..ac2ceae1d3 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -930,6 +930,17 @@ subroutine InitHistory(this, bounds, carbon_type) ptr_patch=data1dptr) end do + ! GRAINC_TO_FOOD_* are default='inactive' because they make more + ! sense to view as instantaneous fields. To view variables as + ! instantaneous fields: + ! 1) Users now cannot set avgflag='I' or 'L' in the code. + ! 2) Instead add lines like these to the user_nl_clm of a case. The + ! last two lines will look different according to each user's needs: + ! hist_fincl2 = 'GRAINC_TO_FOOD_PERHARV' + ! hist_fincl3 = 'GRAINC_TO_FOOD_PERHARV' + ! hist_avgflag_pertape = 'A','I','L180000' + ! hist_nhtfrq = -24,-24,-24 + ! hist_mfilt = 1,1,1 this%repr_grainc_to_food_perharv_patch(begp:endp,:,:) = spval do k = repr_grain_min, repr_grain_max data2dptr => this%repr_grainc_to_food_perharv_patch(:,:,k) @@ -938,8 +949,8 @@ subroutine InitHistory(this, bounds, carbon_type) fname=get_repr_hist_fname(k)//'C_TO_FOOD_PERHARV', & units='gC/m^2', & type2d='mxharvests', & - avgflag='I', & - long_name=get_repr_longname(k)//' C to food per harvest; should only be output annually', & + avgflag='A', & + long_name=get_repr_longname(k)//' C to food per harvest; should only be output annually and as an instantaneous field', & ptr_patch=data2dptr, & default='inactive') end do @@ -951,8 +962,8 @@ subroutine InitHistory(this, bounds, carbon_type) ! e.g., GRAINC_TO_FOOD_ANN fname=get_repr_hist_fname(k)//'C_TO_FOOD_ANN', & units='gC/m^2', & - avgflag='I', & - long_name=get_repr_longname(k)//' C to food harvested per calendar year; should only be output annually', & + avgflag='A', & + long_name=get_repr_longname(k)//' C to food harvested per calendar year; should only be output annually and as an instantaneous field', & ptr_patch=data1dptr, & default='inactive') end do diff --git a/src/biogeochem/CNVegStateType.F90 b/src/biogeochem/CNVegStateType.F90 index e7e61c75bf..f6399b4336 100644 --- a/src/biogeochem/CNVegStateType.F90 +++ b/src/biogeochem/CNVegStateType.F90 @@ -321,9 +321,20 @@ subroutine InitHistory(this, bounds) ptr_patch=this%gddmaturity_patch, default='inactive') ! Per harvest + ! GDDHARV_PERHARV is default='inactive' because it makes more + ! sense to view as an instantaneous field. To view variables as + ! instantaneous fields: + ! 1) Users now cannot set avgflag='I' or 'L' in the code. + ! 2) Instead add lines like these to the user_nl_clm of a case. The + ! last two lines will look different according to each user's needs: + ! hist_fincl2 = 'GDDHARV_PERHARV' + ! hist_fincl3 = 'GDDHARV_PERHARV' + ! hist_avgflag_pertape = 'A','I','L180000' + ! hist_nhtfrq = -24,-24,-24 + ! hist_mfilt = 1,1,1 this%gddmaturity_thisyr(begp:endp,:) = spval call hist_addfld2d (fname='GDDHARV_PERHARV', units='ddays', type2d='mxharvests', & - avgflag='I', long_name='Growing degree days (gdd) needed to harvest; should only be output annually', & + avgflag='A', long_name='Growing degree days (gdd) needed to harvest; should only be output annually and as an instantaneous field', & ptr_patch=this%gddmaturity_thisyr, default='inactive') end if diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index f84c4c1821..fe47a700d7 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -297,49 +297,58 @@ subroutine InitHistory(this, bounds) ptr_patch=this%latbaset_patch, default='inactive') end if + ! SDATES, HDATES make sense as instantaneous fields; to view as such: + ! 1) Users now cannot set avgflag='I' or 'L' in the code. + ! 2) Instead add lines like these to the user_nl_clm of a case. The + ! last two lines will look different according to each user's needs: + ! hist_fincl2 = 'SDATES','HDATES' + ! hist_fincl3 = 'SDATES','HDATES' + ! hist_avgflag_pertape = 'A','I','L180000' + ! hist_nhtfrq = -24,-24,-24 + ! hist_mfilt = 1,1,1 this%sdates_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='SDATES', units='day of year', type2d='mxsowings', & - avgflag='I', long_name='actual crop sowing dates; should only be output annually', & + avgflag='A', long_name='actual crop sowing dates; should only be output annually and as an instantaneous field', & ptr_patch=this%sdates_thisyr_patch, default='inactive') this%sdates_perharv_patch(begp:endp,:) = spval call hist_addfld2d (fname='SDATES_PERHARV', units='day of year', type2d='mxharvests', & - avgflag='I', long_name='actual sowing dates for crops harvested this year; should only be output annually', & + avgflag='A', long_name='actual sowing dates for crops harvested this year; should only be output annually and as an instantaneous field', & ptr_patch=this%sdates_perharv_patch, default='inactive') this%syears_perharv_patch(begp:endp,:) = spval call hist_addfld2d (fname='SYEARS_PERHARV', units='year', type2d='mxharvests', & - avgflag='I', long_name='actual sowing years for crops harvested this year; should only be output annually', & + avgflag='A', long_name='actual sowing years for crops harvested this year; should only be output annually and as an instantaneous field', & ptr_patch=this%syears_perharv_patch, default='inactive') this%hdates_thisyr_patch(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', & + avgflag='A', long_name='actual crop harvest dates; should only be output annually and as an instantaneous field', & ptr_patch=this%hdates_thisyr_patch, default='inactive') this%gddaccum_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='GDDACCUM_PERHARV', units='ddays', type2d='mxharvests', & - avgflag='I', long_name='At-harvest accumulated growing degree days past planting date for crop; should only be output annually', & + avgflag='A', long_name='At-harvest accumulated growing degree days past planting date for crop; should only be output annually and as an instantaneous field', & ptr_patch=this%gddaccum_thisyr_patch, default='inactive') this%hui_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='HUI_PERHARV', units='ddays', type2d='mxharvests', & - avgflag='I', long_name='At-harvest accumulated heat unit index for crop; should only be output annually', & + avgflag='A', long_name='At-harvest accumulated heat unit index for crop; should only be output annually and as an instantaneous field', & ptr_patch=this%hui_thisyr_patch, default='inactive') this%sowing_reason_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='SOWING_REASON', units='unitless', type2d='mxsowings', & - avgflag='I', long_name='Reason for each crop sowing; should only be output annually', & + avgflag='A', long_name='Reason for each crop sowing; should only be output annually and as an instantaneous field', & ptr_patch=this%sowing_reason_thisyr_patch, default='inactive') this%sowing_reason_perharv_patch(begp:endp,:) = spval call hist_addfld2d (fname='SOWING_REASON_PERHARV', units='unitless', type2d='mxharvests', & - avgflag='I', long_name='Reason for sowing of each crop harvested this year; should only be output annually', & + avgflag='A', long_name='Reason for sowing of each crop harvested this year; should only be output annually and as an instantaneous field', & ptr_patch=this%sowing_reason_perharv_patch, default='inactive') this%harvest_reason_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='HARVEST_REASON_PERHARV', units='1 = mature; 2 = max season length; 3 = incorrect Dec. 31 sowing; 4 = sowing today; 5 = sowing tomorrow; 6 = tomorrow == idop; 7 = killed by cold temperature during vernalization', type2d='mxharvests', & - avgflag='I', long_name='Reason for each crop harvest; should only be output annually', & + avgflag='A', long_name='Reason for each crop harvest; should only be output annually and as an instantaneous field', & ptr_patch=this%harvest_reason_thisyr_patch, default='inactive') end subroutine InitHistory diff --git a/src/biogeophys/PhotosynthesisMod.F90 b/src/biogeophys/PhotosynthesisMod.F90 index 5b2c68a0fb..28e56f196f 100644 --- a/src/biogeophys/PhotosynthesisMod.F90 +++ b/src/biogeophys/PhotosynthesisMod.F90 @@ -515,9 +515,18 @@ subroutine InitHistory(this, bounds) ! Don't by default output this rate limiting step as only makes sense if you are outputing ! the others each time-step + ! and viewing this as an instantaneous field. To view as instantaneous: + ! 1) Users now cannot set avgflag='I' or 'L' in the code. + ! 2) Instead add lines like these to the user_nl_clm of a case. The + ! last two lines will look different according to each user's needs: + ! hist_fincl2 = 'FPSN_WC','FPSN_WJ','FPSN_WP' + ! hist_fincl3 = 'FPSN_WC','FPSN_WJ','FPSN_WP' + ! hist_avgflag_pertape = 'A','I','L180000' + ! hist_nhtfrq = -24,-24,-24 + ! hist_mfilt = 1,1,1 this%fpsn_wc_patch(begp:endp) = spval call hist_addfld1d (fname='FPSN_WC', units='umol m-2 s-1', & - avgflag='I', long_name='Rubisco-limited photosynthesis', & + avgflag='A', long_name='Rubisco-limited photosynthesis; should be output as an instantaneous field', & ptr_patch=this%fpsn_wc_patch, set_lake=0._r8, set_urb=0._r8, & default='inactive') @@ -525,7 +534,7 @@ subroutine InitHistory(this, bounds) ! the others each time-step this%fpsn_wj_patch(begp:endp) = spval call hist_addfld1d (fname='FPSN_WJ', units='umol m-2 s-1', & - avgflag='I', long_name='RuBP-limited photosynthesis', & + avgflag='A', long_name='RuBP-limited photosynthesis; should be output as an instantaneous field', & ptr_patch=this%fpsn_wj_patch, set_lake=0._r8, set_urb=0._r8, & default='inactive') @@ -533,7 +542,7 @@ subroutine InitHistory(this, bounds) ! the others each time-step this%fpsn_wp_patch(begp:endp) = spval call hist_addfld1d (fname='FPSN_WP', units='umol m-2 s-1', & - avgflag='I', long_name='Product-limited photosynthesis', & + avgflag='A', long_name='Product-limited photosynthesis; should be output as an instantaneous field', & ptr_patch=this%fpsn_wp_patch, set_lake=0._r8, set_urb=0._r8, & default='inactive') end if diff --git a/src/biogeophys/WaterStateBulkType.F90 b/src/biogeophys/WaterStateBulkType.F90 index ba3f0513c5..184cd30c10 100644 --- a/src/biogeophys/WaterStateBulkType.F90 +++ b/src/biogeophys/WaterStateBulkType.F90 @@ -150,13 +150,25 @@ subroutine InitBulkHistory(this, bounds) ptr_col=this%int_snow_col, l2g_scale_type='ice', & default='inactive') + ! SNOW_PERSISTENCE is default='inactive' because as the "length of + ! time of continuous snow cover" it makes more sense to view as an + ! instantaneous field. To view variables as instantaneous fields: + ! 1) Users now cannot set avgflag='I' or 'L' in the code. + ! 2) Instead add lines like these to the user_nl_clm of a case. The + ! last two lines will look different according to each user's needs: + ! hist_fincl2 = 'SNOW_PERSISTENCE' + ! hist_fincl3 = 'SNOW_PERSISTENCE' + ! hist_avgflag_pertape = 'A','I','L180000' + ! hist_nhtfrq = -24,-24,-24 + ! hist_mfilt = 1,1,1 this%snow_persistence_col(begc:endc) = spval call hist_addfld1d ( & fname=this%info%fname('SNOW_PERSISTENCE'), & units='seconds', & - avgflag='I', & - long_name=this%info%lname('Length of time of continuous snow cover (nat. veg. landunits only)'), & - ptr_col=this%snow_persistence_col, l2g_scale_type='natveg') + avgflag='A', & + long_name=this%info%lname('Length of time of continuous snow cover (nat. veg. landunits only); should be output as an instantaneous field'), & + ptr_col=this%snow_persistence_col, l2g_scale_type='natveg', & + default='inactive') end subroutine InitBulkHistory diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index 7e07c2fcd7..2c2bea651a 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -531,7 +531,8 @@ subroutine masterlist_addfld (fname, numdims, type1d, type1d_out, & character(len=*),parameter :: subname = 'masterlist_addfld' !------------------------------------------------------------------------ - if (.not. avgflag_valid(avgflag, blank_valid=.true.)) then + if (.not. avgflag_valid(avgflag, blank_valid=.true., & + local_valid = .false., instantaneous_valid=.false.)) then write(iulog,*) trim(subname),' ERROR: unknown averaging flag=', avgflag call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -740,7 +741,8 @@ subroutine masterlist_make_active (name, tape_index, avgflag) end if if (present(avgflag)) then - if (.not. avgflag_valid(avgflag, blank_valid=.true.)) then + if (.not. avgflag_valid(avgflag, blank_valid=.true., & + local_valid = .false., instantaneous_valid=.false.)) then write(iulog,*) trim(subname),' ERROR: unknown averaging flag=', avgflag call endrun(msg=errMsg(sourcefile, __LINE__)) endif @@ -785,7 +787,8 @@ subroutine masterlist_change_timeavg (t) !----------------------------------------------------------------------- avgflag = hist_avgflag_pertape(t) - if (.not. avgflag_valid(avgflag, blank_valid = .false.)) then + if (.not. avgflag_valid(avgflag, blank_valid = .false., & + local_valid = .true., instantaneous_valid=.true.)) then write(iulog,*) trim(subname),' ERROR: unknown avgflag=',avgflag call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1154,6 +1157,7 @@ subroutine htape_addfld (t, f, avgflag) integer :: beg1d,end1d ! beginning and ending indices for this field (assume already set) integer :: num1d_out ! history output 1d size type(bounds_type) :: bounds + character(len=avgflag_strlen) :: avgflag_temp ! local copy of hist_avgflag_pertape(t) character(len=*),parameter :: subname = 'htape_addfld' !----------------------------------------------------------------------- @@ -1273,7 +1277,8 @@ subroutine htape_addfld (t, f, avgflag) ! Set time averaging flag based on masterlist setting or ! override the default averaging flag with namelist setting - if (.not. avgflag_valid(avgflag, blank_valid=.true.)) then + if (.not. avgflag_valid(avgflag, blank_valid=.true., & + local_valid = .false., instantaneous_valid=.false.)) then write(iulog,*) trim(subname),' ERROR: unknown avgflag=', avgflag call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1284,6 +1289,14 @@ subroutine htape_addfld (t, f, avgflag) tape(t)%hlist(n)%avgflag = avgflag end if + ! Override this field's avgflag if the namelist has set this tape to + ! - instantaneous or + ! - local time + avgflag_temp = hist_avgflag_pertape(t) + if (avgflag_temp == 'I' .or. avgflag_temp(1:1) == 'L') then + tape(t)%hlist(n)%avgflag = avgflag_temp + end if + end subroutine htape_addfld !----------------------------------------------------------------------- @@ -3068,6 +3081,7 @@ subroutine htape_timeconst(t, mode) integer :: mcdate ! current date integer :: yr,mon,day,nbsec ! year,month,day,seconds components of a date integer :: hours,minutes,secs ! hours,minutes,seconds of hh:mm:ss + character(len= 12) :: step_or_bounds ! string used in long_name of several time variables character(len= 10) :: basedate ! base date (yyyymmdd) character(len= 8) :: basesec ! base seconds character(len= 8) :: cdate ! system date @@ -3250,8 +3264,18 @@ subroutine htape_timeconst(t, mode) dim1id(1) = time_dimid str = 'days since ' // basedate // " " // basesec - call ncd_defvar(nfid(t), 'time', tape(t)%ncprec, 1, dim1id, varid, & - long_name='time',units=str) + if (tape(t)%hlist(1)%avgflag /= 'I') then ! NOT instantaneous fields tape + step_or_bounds = 'time_bounds' + long_name = 'time at exact middle of ' // step_or_bounds + call ncd_defvar(nfid(t), 'time', tape(t)%ncprec, 1, dim1id, varid, & + long_name=long_name, units=str) + call ncd_putatt(nfid(t), varid, 'bounds', 'time_bounds') + else ! instantaneous fields tape + step_or_bounds = 'time step' + long_name = 'time at end of ' // step_or_bounds + call ncd_defvar(nfid(t), 'time', tape(t)%ncprec, 1, dim1id, varid, & + long_name=long_name, units=str) + end if cal = get_calendar() if ( trim(cal) == NO_LEAP_C )then caldesc = "noleap" @@ -3259,11 +3283,11 @@ subroutine htape_timeconst(t, mode) caldesc = "gregorian" end if call ncd_putatt(nfid(t), varid, 'calendar', caldesc) - call ncd_putatt(nfid(t), varid, 'bounds', 'time_bounds') dim1id(1) = time_dimid + long_name = 'current date (YYYYMMDD) at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mcdate', ncd_int, 1, dim1id , varid, & - long_name = 'current date (YYYYMMDD)') + long_name = long_name) ! ! add global attribute time_period_freq ! @@ -3290,18 +3314,23 @@ subroutine htape_timeconst(t, mode) call ncd_putatt(nfid(t), ncd_global, 'time_period_freq', & trim(time_period_freq)) + long_name = 'current seconds of current date at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mcsec' , ncd_int, 1, dim1id , varid, & - long_name = 'current seconds of current date', units='s') + long_name = long_name, units='s') + long_name = 'current day (from base day) at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mdcur' , ncd_int, 1, dim1id , varid, & - long_name = 'current day (from base day)') + long_name = long_name) + long_name = 'current seconds of current day at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mscur' , ncd_int, 1, dim1id , varid, & - long_name = 'current seconds of current day') + long_name = long_name) call ncd_defvar(nfid(t) , 'nstep' , ncd_int, 1, dim1id , varid, & long_name = 'time step') dim2id(1) = hist_interval_dimid; dim2id(2) = time_dimid - call ncd_defvar(nfid(t), 'time_bounds', ncd_double, 2, dim2id, varid, & - long_name = 'history time interval endpoints') + if (tape(t)%hlist(1)%avgflag /= 'I') then ! NOT instantaneous fields tape + call ncd_defvar(nfid(t), 'time_bounds', ncd_double, 2, dim2id, varid, & + long_name = 'history time interval endpoints') + end if dim2id(1) = strlen_dimid; dim2id(2) = time_dimid call ncd_defvar(nfid(t), 'date_written', ncd_char, 2, dim2id, varid) @@ -3329,13 +3358,16 @@ subroutine htape_timeconst(t, mode) call ncd_io('mscur' , mscur , 'write', nfid(t), nt=tape(t)%ntimes) call ncd_io('nstep' , nstep , 'write', nfid(t), nt=tape(t)%ntimes) - time = mdcur + mscur/secspday + timedata(1) = tape(t)%begtime ! beginning time + timedata(2) = mdcur + mscur/secspday ! end time + if (tape(t)%hlist(1)%avgflag /= 'I') then ! NOT instantaneous fields tape + time = (timedata(1) + timedata(2)) * 0.5_r8 + call ncd_io('time_bounds', timedata, 'write', nfid(t), nt=tape(t)%ntimes) + else + time = timedata(2) + end if call ncd_io('time' , time , 'write', nfid(t), nt=tape(t)%ntimes) - timedata(1) = tape(t)%begtime - timedata(2) = time - call ncd_io('time_bounds', timedata, 'write', nfid(t), nt=tape(t)%ntimes) - call getdatetime (cdate, ctime) call ncd_io('date_written', cdate, 'write', nfid(t), nt=tape(t)%ntimes) @@ -5930,7 +5962,8 @@ subroutine hist_do_disp (ntapes, hist_ntimes, hist_mfilt, if_stop, if_disphist, end subroutine hist_do_disp !----------------------------------------------------------------------- - function avgflag_valid(avgflag, blank_valid) result(valid) + function avgflag_valid(avgflag, blank_valid, local_valid, & + instantaneous_valid) result(valid) ! ! !DESCRIPTION: ! Returns true if the given avgflag is a valid option, false if not @@ -5943,6 +5976,8 @@ function avgflag_valid(avgflag, blank_valid) result(valid) logical :: valid ! function result character(len=*), intent(in) :: avgflag logical, intent(in) :: blank_valid ! whether ' ' is a valid avgflag in this context + logical, intent(in) :: local_valid ! is 'L' a valid avgflag or not + logical, intent(in) :: instantaneous_valid ! is 'I' a valid avgflag or not ! ! !LOCAL VARIABLES: @@ -5958,11 +5993,12 @@ function avgflag_valid(avgflag, blank_valid) result(valid) else if (avgflag == ' ' .and. blank_valid) then valid = .true. - else if (avgflag == 'A' .or. avgflag == 'I' .or. & - avgflag == 'X' .or. avgflag == 'M' .or. & + else if (avgflag == 'I' .and. instantaneous_valid) then + valid = .true. + else if (avgflag == 'A' .or. avgflag == 'X' .or. avgflag == 'M' .or. & avgflag == 'SUM') then valid = .true. - else if (avgflag(1:1) == 'L') then + else if (avgflag(1:1) == 'L' .and. local_valid) then dtime = get_step_size() if ( len_trim(avgflag) < 6 )then valid = .false.