diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 089e9fbb12..c02e20b678 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -27,6 +27,7 @@ d866510188d26d51bcd6d37239283db690af7e82
e096358c832ab292ddfd22dd5878826c7c788968
475831f0fb0e31e97f630eac4e078c886558b61c
fd5f177131d63d39e79a13918390bdfb642d781e
+a51816e0de380300b69db9fc3e2c7fa83b267b64
# Ran SystemTests and python/ctsm through black python formatter
5364ad66eaceb55dde2d3d598fe4ce37ac83a93c
8056ae649c1b37f5e10aaaac79005d6e3a8b2380
diff --git a/.gitmodules b/.gitmodules
index 6947e06c73..9aeb7d4de0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -44,7 +44,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CISM-wrapper
[submodule "rtm"]
path = components/rtm
url = https://github.com/ESCOMP/RTM
-fxtag = rtm1_0_80
+fxtag = rtm1_0_86
fxrequired = ToplevelRequired
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
fxDONOTUSEurl = https://github.com/ESCOMP/RTM
@@ -52,7 +52,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/RTM
[submodule "mosart"]
path = components/mosart
url = https://github.com/ESCOMP/MOSART
-fxtag = mosart1.1.02
+fxtag = mosart1.1.07
fxrequired = ToplevelRequired
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
fxDONOTUSEurl = https://github.com/ESCOMP/MOSART
diff --git a/cime_config/testdefs/ExpectedTestFails.xml b/cime_config/testdefs/ExpectedTestFails.xml
index fa7f9c1844..9735c02f4c 100644
--- a/cime_config/testdefs/ExpectedTestFails.xml
+++ b/cime_config/testdefs/ExpectedTestFails.xml
@@ -126,28 +126,7 @@
#2310
-
-
-
- FAIL
- #2914
-
-
-
-
-
- FAIL
- #2914
-
-
-
-
-
- FAIL
- #2905
-
-
-
+
FAIL
@@ -242,23 +221,12 @@
-
- FAIL
- #2454
-
FAIL
#2325
-
-
- FAIL
- #2454
-
-
-
FAIL
diff --git a/components/mosart b/components/mosart
index e2ffe00004..330574fbd8 160000
--- a/components/mosart
+++ b/components/mosart
@@ -1 +1 @@
-Subproject commit e2ffe00004cc416cfc8bcfae2a949474075c1d1f
+Subproject commit 330574fbd8a4810b7a168175690cbf7e1a7f6dab
diff --git a/components/rtm b/components/rtm
index b3dfcfbba5..26e96f500b 160000
--- a/components/rtm
+++ b/components/rtm
@@ -1 +1 @@
-Subproject commit b3dfcfbba58c151ac5a6ab513b3515ef3deff798
+Subproject commit 26e96f500b9500b32a870db20eed6b1bd37587ea
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 1b37b4be63..2c08950b2d 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,4 +1,269 @@
===============================================================
+Tag name: ctsm5.3.020
+Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu)
+Date: Fri Jan 17 12:21:24 MST 2025
+One-line Summary: Merge b4b-dev
+
+Purpose and description of changes
+----------------------------------
+
+Merging b4b-dev and ctsm5.3.019. Includes some improvements to test list / expected failures.
+
+
+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.]
+
+[ ] clm6_0
+
+[ ] clm5_0
+
+[ ] ctsm5_0-nwp
+
+[ ] clm4_5
+
+
+Notes of particular relevance for developers:
+---------------------------------------------
+
+Changes to tests or testing:
+- New test suite: Useful for redoing tests that failed due to https://github.com/ESCOMP/CTSM/issues/2916, after having replaced libraries/mpi-serial with a fresh copy.
+
+
+Testing summary:
+----------------
+
+ regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing):
+
+ derecho ----- OK
+ izumi ------- OK
+
+
+Other details
+-------------
+[Remove any lines that don't apply. Remove entire section if nothing applies.]
+
+List any git submodules updated (cime, rtm, mosart, cism, fates, etc.):
+
+Pull Requests that document the changes (include PR ids):
+- ESCOMP/CTSM#2938: ctsm5.3.020: Merge b4b-dev 2025-01-16 (https://github.com/ESCOMP/CTSM/pull/2938)
+
+===============================================================
+===============================================================
+Tag name: ctsm5.3.019
+Originator(s): olyson (Keith Oleson, UCAR/TSS)
+Date: Tue 14 Jan 2025 02:46:11 PM MST
+One-line Summary: Stop running 0th time step
+
+Purpose and description of changes
+----------------------------------
+ As with the last tag, this is also for consistency with CAM.
+
+Contributors
+------------
+ Bill Sacks. In the final steps, also slevis.
+
+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.]
+
+[ ] clm6_0
+
+[ ] clm5_0
+
+[ ] ctsm5_0-nwp
+
+[ ] clm4_5
+
+
+Bugs fixed
+----------
+List of CTSM issues fixed (include CTSM Issue # and description) [one per line]:
+ Fixes #925
+
+Notes of particular relevance for developers:
+---------------------------------------------
+Caveats for developers (e.g., code that is duplicated that requires double maintenance):
+ Same or similar changes needed separately in clm, in mosart, and in rtm.
+
+Changes to tests or testing:
+ FAIL RXCROPMATURITYSKIPGEN_Ld1097.f10_f10_mg37.IHistClm60BgcCrop.derecho_intel.clm-cropMonthOutput RUN
+ I did not label this failure EXPECTED because the fix is planned for the next tag, ctsm5.3.020.
+
+ I resolved the izumi nag tests that failed to build (due to a bug in rtm and mosart) by introducing the bug-fix manually, as explained here:
+https://github.com/ESCOMP/CTSM/pull/2084#issuecomment-2584164690
+ In ctsm5.3.020 we plan to update to the rtm/mosart tags that include the fix.
+
+Testing summary:
+----------------
+
+ [PASS means all tests PASS; OK means tests PASS other than expected fails.]
+
+ build-namelist tests (if CLMBuildNamelist.pm has changed):
+
+ derecho - PASS
+
+ python testing (if python code has changed; see instructions in python/README.md; document testing done):
+
+ derecho - PASS
+
+ regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing):
+
+ derecho ----- OK
+ izumi ------- OK
+
+ mosart
+ derecho ----- OK
+ izumi ------- OK
+
+ rtm
+ derecho ----- OK
+
+If the tag used for baseline comparisons was NOT the previous tag, note that here:
+ I repeated the rtm & mosart test-suites with mosart1.1.04 instead of 06 and rtm1_0_82 instead of 84 (all else the same) and compared against the new baselines mosart1.1.06-ctsm5.3.019 and rtm1_0_84-ctsm5.3.019. These gave b4b identical answers.
+
+Answer changes
+--------------
+
+Changes answers relative to baseline: Yes
+
+ Summarize any changes to answers, i.e.,
+ - what code configurations: All
+ - what platforms/compilers: All
+ - nature of change: larger than roundoff/same climate
+
+ Caveat: We see diffs in mosart and cpl output that will be eliminated in ctsm5.3.020. They are discussed here:
+https://github.com/ESCOMP/CTSM/pull/2838#issuecomment-2477608383
+https://github.com/ESCOMP/MOSART/issues/103#issuecomment-2479679014
+
+Other details
+-------------
+List any git submodules updated (cime, rtm, mosart, cism, fates, etc.):
+ rtm and mosart were already updated in the previous tag (ctsm5.3.018) to include the corresponding rtm and mosart tags
+
+Pull Requests that document the changes (include PR ids):
+ https://github.com/ESCOMP/ctsm/pull/2084
+ https://github.com/ESCOMP/MOSART/pull/67
+ https://github.com/ESCOMP/RTM/pull/37
+
+===============================================================
+===============================================================
+Tag name: ctsm5.3.018
+Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310)
+Date: Fri 10 Jan 2025 05:37:08 PM MST
+One-line Summary: Change history time to be the middle of the time bounds
+
+Purpose and description of changes
+----------------------------------
+ Making the change to be consistent with CAM and to make history output more intuitive.
+
+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.]
+
+[ ] clm6_0
+
+[ ] clm5_1
+
+[ ] clm5_0
+
+[ ] ctsm5_0-nwp
+
+[ ] clm4_5
+
+
+Bugs fixed
+----------
+List of CTSM issues fixed (include CTSM Issue # and description) [one per line]:
+ Partly addresses issue #1059
+
+Notes of particular relevance for users
+---------------------------------------
+Caveats for users (e.g., need to interpolate initial conditions):
+ The history time variable now equals the middle of the time bounds.
+ Instantaneous history tapes now do not include time bounds.
+ Mixed history tapes do not change the treatment of instantaneous fields or move them to separate tapes, yet.
+
+Notes of particular relevance for developers:
+---------------------------------------------
+Caveats for developers (e.g., code that is duplicated that requires double maintenance):
+ Same changes are needed separately in clm, in mosart, and in rtm.
+
+Changes to tests or testing:
+ This tag introduces changes to the mosart/rtm testlists.
+
+ FAIL RXCROPMATURITYSKIPGEN_Ld1097.f10_f10_mg37.IHistClm60BgcCrop.derecho_intel.clm-cropMonthOutput RUN
+ I did not label this failure EXPECTED because the fix comes in later in this series of "history" tags, in particular ctsm5.3.020.
+
+ I resolved the izumi nag tests that failed to build (due to a bug in rtm and mosart) by introducing the bug-fix manually, as explained here:
+https://github.com/ESCOMP/CTSM/pull/2084#issuecomment-2584164690
+ In the next tag we expect to update to the rtm/mosart tags that include the fix.
+
+Testing summary:
+----------------
+
+ [PASS means all tests PASS; OK means tests PASS other than expected fails.]
+
+ build-namelist tests
+
+ derecho - PASS
+
+ python testing (if python code has changed; see instructions in python/README.md; document testing done):
+
+ derecho - PASS
+
+ regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing):
+
+ derecho ----- OK
+ izumi ------- OK
+
+ mosart
+ derecho ----- OK
+ izumi ------- OK
+
+ rtm
+ derecho ----- OK
+
+Answer changes
+--------------
+
+Changes answers relative to baseline: Only time variable, plus read caveat
+
+ Summarize any changes to answers, i.e.,
+ - what code configurations: all
+ - what platforms/compilers: all
+ - nature of change: only the time variable
+
+ Caveat: We see diffs in mosart and cpl output that will be eliminated later in this series of "history" tags, in particular ctsm5.3.020. They are discussed here:
+https://github.com/ESCOMP/CTSM/pull/2838#issuecomment-2477608383
+https://github.com/ESCOMP/MOSART/issues/103#issuecomment-2479679014
+
+Other details
+-------------
+List any git submodules updated (cime, rtm, mosart, cism, fates, etc.):
+ rtm, mosart (see related note in ctsm5.3.019)
+
+Pull Requests that document the changes (include PR ids):
+ https://github.com/ESCOMP/ctsm/pull/2838
+ https://github.com/ESCOMP/MOSART/pull/70
+ https://github.com/ESCOMP/RTM/issues/54
+ https://github.com/ESCOMP/MOSART/pull/106
+ https://github.com/ESCOMP/RTM/pull/39
+
+===============================================================
+===============================================================
Tag name: ctsm5.3.017
Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310)
Date: Thu 09 Jan 2025 11:56:43 AM MST
diff --git a/doc/ChangeSum b/doc/ChangeSum
index 545a02ff25..98739639a4 100644
--- a/doc/ChangeSum
+++ b/doc/ChangeSum
@@ -1,5 +1,8 @@
Tag Who Date Summary
============================================================================================================================
+ ctsm5.3.020 samrabin 01/17/2025 Merge b4b-dev
+ ctsm5.3.019 olyson 01/14/2025 Stop running 0th time step
+ ctsm5.3.018 slevis 01/10/2025 Change history time to be the middle of the time bounds
ctsm5.3.017 slevis 01/09/2025 Merge tmp-241219 branch to master
tmp-241219.n03.ctsm5.3.016 01/09/2025 Bug fix for izumi nag tests to pass (slevis)
tmp-241219.n02.ctsm5.3.016 01/08/2025 FATES hydro test update (glemieux)
diff --git a/python/ctsm/crop_calendars/cropcal_module.py b/python/ctsm/crop_calendars/cropcal_module.py
index 719d352665..3ea084e1d2 100644
--- a/python/ctsm/crop_calendars/cropcal_module.py
+++ b/python/ctsm/crop_calendars/cropcal_module.py
@@ -443,10 +443,7 @@ def import_output(
)
# Convert time axis to integer year, saving original as 'cftime'
- this_ds_gs = this_ds_gs.assign_coords(
- {"cftime": this_ds["time_bounds"].isel({"hist_interval": 0})}
- )
- this_ds_gs = this_ds_gs.assign_coords({"time": [t.year for t in this_ds_gs["cftime"].values]})
+ this_ds_gs = convert_time_to_int_year(filename, this_ds, this_ds_gs)
# Get number of harvests
this_ds_gs["NHARVESTS"] = (this_ds_gs["GDDHARV_PERHARV"] > 0).sum(dim="mxharvests")
@@ -458,6 +455,35 @@ def import_output(
return this_ds_gs, any_bad
+def convert_time_to_int_year(filename, this_ds, this_ds_gs):
+ """
+ Convert time axis to integer year, saving original as 'cftime'
+ """
+ if "time_bounds" in this_ds:
+ # Always true before PR #2838, when even files with all instantaneous variables got
+ # time_bounds saved. After that PR (and before the segregation of instantaneous and other
+ # variables onto separate files), files with an instantaneous variable first in their list
+ # do not get time_bounds saved.
+ this_ds_gs = this_ds_gs.assign_coords(
+ {"cftime": this_ds["time_bounds"].isel({"hist_interval": 0})}
+ )
+ this_ds_gs = this_ds_gs.assign_coords(
+ {"time": [t.year for t in this_ds_gs["cftime"].values]}
+ )
+ elif this_ds["time"].attrs["long_name"] == "time at end of time step":
+ # This is an "instantaneous file."
+ this_ds_gs = this_ds_gs.assign_coords({"cftime": this_ds["time"]})
+ this_ds_gs = this_ds_gs.assign_coords(
+ {"time": [t.year - 1 for t in this_ds_gs["cftime"].values]}
+ )
+ else:
+ raise RuntimeError(
+ f"{filename} is neither an instantaneous nor a combined/non-instantaneous file."
+ )
+
+ return this_ds_gs
+
+
def handle_zombie_crops(this_ds):
"""
When doing transient runs, it's somehow possible for crops in newly-active patches to be
diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py
index 81c71e2a51..e83eb7bb50 100644
--- a/python/ctsm/crop_calendars/generate_gdds_functions.py
+++ b/python/ctsm/crop_calendars/generate_gdds_functions.py
@@ -60,6 +60,7 @@ def error(logger, string):
"""
Simultaneously print ERROR messages to console and to log file
"""
+ print(string)
logger.error(string)
raise RuntimeError(string)
@@ -271,7 +272,7 @@ def import_and_process_1yr(
else:
chunks = None
- # Get h2 file (list)
+ # Get h1 file (list)
h1_pattern = os.path.join(indir, "*h1.*.nc")
h1_filelist = glob.glob(h1_pattern)
if not h1_filelist:
@@ -551,13 +552,14 @@ def import_and_process_1yr(
log(logger, " Importing accumulated GDDs...")
clm_gdd_var = "GDDACCUM"
my_vars = [clm_gdd_var, "GDDHARV"]
- pattern = os.path.join(indir, f"*h2.{this_year-1}-01-01*.nc")
- h2_files = glob.glob(pattern)
- if not h2_files:
- pattern = os.path.join(indir, f"*h2.{this_year-1}-01-01*.nc.base")
+ patterns = [f"*h2.{this_year-1}-01*.nc", f"*h2.{this_year-1}-01*.nc.base"]
+ for p in patterns:
+ pattern = os.path.join(indir, p)
h2_files = glob.glob(pattern)
- if not h2_files:
- error(logger, f"No files found matching pattern '*h2.{this_year-1}-01-01*.nc(.base)'")
+ if h2_files:
+ break
+ if not h2_files:
+ error(logger, f"No files found matching patterns: {patterns}")
h2_ds = import_ds(
h2_files,
my_vars=my_vars,
diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90
index 73eadbb1a9..5ad4fb1157 100644
--- a/src/biogeochem/CNPhenologyMod.F90
+++ b/src/biogeochem/CNPhenologyMod.F90
@@ -392,19 +392,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, &
soilstate_inst, temperature_inst, atm2lnd_inst, wateratm2lndbulk_inst, cnveg_state_inst, &
cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst)
- ! BACKWARDS_COMPATIBILITY(wjs, 2022-02-03) Old restart files generated at the end
- ! of the year can indicate that a crop was panted on Jan 1, because that used to be
- ! the time given to the last time step of the year. This would cause problems if we
- ! ran CropPhenology in time step 0, because now time step 0 is labeled as Dec 31,
- ! so CropPhenology would see the crop as having been planted 364 days ago, and so
- ! would want to harvest this newly-planted crop. To avoid this situation, we avoid
- ! calling CropPhenology on time step 0.
- !
- ! This .not. is_first_step() condition can be removed either when we can rely on
- ! all restart files having been generated with
- ! https://github.com/ESCOMP/CTSM/issues/1623 resolved, or we stop having a time
- ! step 0 (https://github.com/ESCOMP/CTSM/issues/925).
- if (num_pcropp > 0 .and. .not. is_first_step()) then
+ if (num_pcropp > 0) then
call CropPhenology(num_pcropp, filter_pcropp, &
waterdiagnosticbulk_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, &
cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, &
diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90
index 706d52da27..dd20ce50a2 100644
--- a/src/biogeochem/CNVegetationFacade.F90
+++ b/src/biogeochem/CNVegetationFacade.F90
@@ -1285,7 +1285,7 @@ subroutine EndOfTimeStepVegDynamics(this, bounds, num_natvegp, filter_natvegp, &
! Call dv (dynamic vegetation) at last time step of year
call t_startf('d2dgvm')
- if (is_end_curr_year() .and. .not. is_first_step()) then
+ if (is_end_curr_year()) then
! Get date info. kyr is used in lpj(). At end of first year, kyr = 2.
call get_curr_date(yr, mon, day, sec)
@@ -1337,7 +1337,7 @@ subroutine WriteHistory(this, bounds)
! Write to CNDV history buffer if appropriate
if (use_cndv) then
- if (is_end_curr_year() .and. .not. is_first_step()) then
+ if (is_end_curr_year()) then
call t_startf('clm_drv_io_hdgvm')
call CNDVHist( bounds, this%dgvs_inst )
if (masterproc) write(iulog,*) 'Annual CNDV calculations are complete'
diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90
index 0f650a4a9f..54395c4668 100644
--- a/src/biogeochem/CropType.F90
+++ b/src/biogeochem/CropType.F90
@@ -930,7 +930,7 @@ subroutine CropIncrementYear (this, num_pcropp, filter_pcropp)
! Update nyrs when it's the end of the year (unless it's the very start of the
! run). This assumes that, if this patch is active at the end of the year, then it was
! active for the whole year.
- if ((kmo == 1 .and. kda == 1 .and. mcsec == 0) .and. .not. is_first_step()) then
+ if ((kmo == 1 .and. kda == 1 .and. mcsec == 0)) then
do fp = 1, num_pcropp
p = filter_pcropp(fp)
diff --git a/src/biogeochem/dynCNDVMod.F90 b/src/biogeochem/dynCNDVMod.F90
index 76382d175b..d95313772a 100644
--- a/src/biogeochem/dynCNDVMod.F90
+++ b/src/biogeochem/dynCNDVMod.F90
@@ -99,7 +99,7 @@ subroutine dynCNDV_interp( bounds, dgvs_inst)
patch%wtcol(p) = dgvs_inst%fpcgrid_patch(p) + &
wt1 * (dgvs_inst%fpcgridold_patch(p) - dgvs_inst%fpcgrid_patch(p))
- if (mon==1 .and. day==1 .and. sec==dtime .and. nstep>0) then
+ if (mon==1 .and. day==1 .and. sec==dtime) then
dgvs_inst%fpcgridold_patch(p) = dgvs_inst%fpcgrid_patch(p)
end if
end if
diff --git a/src/cpl/lilac/lnd_comp_esmf.F90 b/src/cpl/lilac/lnd_comp_esmf.F90
index 31922c9671..0aa0fc9f81 100644
--- a/src/cpl/lilac/lnd_comp_esmf.F90
+++ b/src/cpl/lilac/lnd_comp_esmf.F90
@@ -559,7 +559,6 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc)
integer :: nstep ! time step index
logical :: rstwr ! .true. ==> write restart file before returning
logical :: nlend ! .true. ==> last time-step
- logical :: dosend ! true => send data back to driver
logical :: doalb ! .true. ==> do albedo calculation on this time step
real(r8) :: nextsw_cday ! calday from clock of next radiation computation
real(r8) :: caldayp1 ! ctsm calday plus dtime offset
@@ -626,161 +625,146 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc)
!--------------------------------
dtime = get_step_size()
- dosend = .false.
- do while(.not. dosend)
-
- ! We assume that the land model time step matches the coupling interval. However,
- ! we still need this while loop to handle the initial time step (time 0). We may
- ! want to get rid of this time step 0 in the lilac coupling, at which point we
- ! should be able to remove this while loop and dosend variable.
- !
- ! See also https://github.com/ESCOMP/CTSM/issues/925
- nstep = get_nstep()
- if (nstep > 0) then
- dosend = .true.
- end if
- !--------------------------------
- ! Determine calendar day info
- !--------------------------------
+ ! We assume that the land model time step matches the coupling interval.
+ nstep = get_nstep()
- calday = get_curr_calday(reuse_day_365_for_day_366=.true.)
- caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.)
+ !--------------------------------
+ ! Determine calendar day info
+ !--------------------------------
- !--------------------------------
- ! Get time of next atmospheric shortwave calculation
- !--------------------------------
+ calday = get_curr_calday(reuse_day_365_for_day_366=.true.)
+ caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.)
- ! TODO(NS): nextsw_cday should come directly from atmosphere!
- ! For now I am setting nextsw_cday to be the same caldayp1
- !
- ! See also https://github.com/ESCOMP/CTSM/issues/860
+ !--------------------------------
+ ! Get time of next atmospheric shortwave calculation
+ !--------------------------------
- nextsw_cday = calday
- if (masterproc) then
- write(iulog,*) trim(subname) // '... nextsw_cday is : ', nextsw_cday
- end if
+ ! TODO(NS): nextsw_cday should come directly from atmosphere!
+ ! For now I am setting nextsw_cday to be the same caldayp1
+ !
+ ! See also https://github.com/ESCOMP/CTSM/issues/860
- !--------------------------------
- ! Obtain orbital values
- !--------------------------------
-
- call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf )
- call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf )
-
- if (masterproc) then
- write(iulog,*) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
- write(iulog,F02) 'nextsw_cday is : ', nextsw_cday
- write(iulog,F02) 'calday is : ', calday
- write(iulog,F02) 'eccen is : ', eccen
- write(iulog,F02) 'mvelpp is : ', mvelpp
- write(iulog,F02) 'lambm0 is : ', lambm0
- write(iulog,F02) 'obliqr is : ', obliqr
- write(iulog,F02) 'declin is : ', declin
- write(iulog,F02) 'declinp1 is : ', declinp1
- write(iulog,* ) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
- end if
+ nextsw_cday = calday
+ if (masterproc) then
+ write(iulog,*) trim(subname) // '... nextsw_cday is : ', nextsw_cday
+ end if
- !--------------------------------
- ! Determine doalb based on nextsw_cday sent from atm model
- !--------------------------------
-
- if (nstep == 0) then
- doalb = .false.
- nextsw_cday = caldayp1
- else if (nstep == 1) then
- !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8)
- doalb = .false.
- else
- doalb = (nextsw_cday >= -0.5_r8)
- end if
+ !--------------------------------
+ ! Obtain orbital values
+ !--------------------------------
- if (masterproc) then
- write(iulog,*) '------------ LILAC ----------------'
- write(iulog,*) 'nstep : ', nstep
- write(iulog,*) 'calday : ', calday
- write(iulog,*) 'caldayp1 : ', caldayp1
- write(iulog,*) 'nextsw_cday : ', nextsw_cday
- write(iulog,*) 'doalb : ', doalb
- write(iulog,*) '-------------------------------------'
- end if
+ call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf )
+ call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf )
- call update_rad_dtime(doalb)
+ if (masterproc) then
+ write(iulog,*) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
+ write(iulog,F02) 'nextsw_cday is : ', nextsw_cday
+ write(iulog,F02) 'calday is : ', calday
+ write(iulog,F02) 'eccen is : ', eccen
+ write(iulog,F02) 'mvelpp is : ', mvelpp
+ write(iulog,F02) 'lambm0 is : ', lambm0
+ write(iulog,F02) 'obliqr is : ', obliqr
+ write(iulog,F02) 'declin is : ', declin
+ write(iulog,F02) 'declinp1 is : ', declinp1
+ write(iulog,* ) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
+ end if
- !--------------------------------
- ! Determine if time to stop
- !--------------------------------
+ !--------------------------------
+ ! Determine doalb based on nextsw_cday sent from atm model
+ !--------------------------------
- call ESMF_ClockGetAlarm(clock, alarmname='lilac_stop_alarm', alarm=alarm, rc=rc)
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ if (nstep == 1) then
+ !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8)
+ doalb = .false.
+ else
+ doalb = (nextsw_cday >= -0.5_r8)
+ end if
- if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- nlend = .true.
- call ESMF_AlarmRingerOff( alarm, rc=rc )
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- else
- nlend = .false.
- endif
- if (masterproc) then
- write(iulog,*)' stop alarm is ',nlend
- end if
+ if (masterproc) then
+ write(iulog,*) '------------ LILAC ----------------'
+ write(iulog,*) 'nstep : ', nstep
+ write(iulog,*) 'calday : ', calday
+ write(iulog,*) 'caldayp1 : ', caldayp1
+ write(iulog,*) 'nextsw_cday : ', nextsw_cday
+ write(iulog,*) 'doalb : ', doalb
+ write(iulog,*) '-------------------------------------'
+ end if
- !--------------------------------
- ! Determine if time to write restart
- !--------------------------------
+ call update_rad_dtime(doalb)
- call ESMF_ClockGetAlarm(clock, alarmname='lilac_restart_alarm', alarm=alarm, rc=rc)
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ !--------------------------------
+ ! Determine if time to stop
+ !--------------------------------
- if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- rstwr = .true.
- call ESMF_AlarmRingerOff( alarm, rc=rc )
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- else
- rstwr = .false.
- endif
- if (masterproc) then
- write(iulog,*)' restart alarm is ',rstwr
- end if
+ call ESMF_ClockGetAlarm(clock, alarmname='lilac_stop_alarm', alarm=alarm, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
- !--------------------------------
- ! Run CTSM
- !--------------------------------
+ if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ nlend = .true.
+ call ESMF_AlarmRingerOff( alarm, rc=rc )
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ else
+ nlend = .false.
+ endif
+ if (masterproc) then
+ write(iulog,*)' stop alarm is ',nlend
+ end if
- call t_barrierf('sync_ctsm_run1', mpicom)
+ !--------------------------------
+ ! Determine if time to write restart
+ !--------------------------------
- ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of
- ! the timestep and is preferred for restart file names
- ! TODO: is this correct for lilac?
+ call ESMF_ClockGetAlarm(clock, alarmname='lilac_restart_alarm', alarm=alarm, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
- call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc)
+ if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
if (ChkErr(rc,__LINE__,u_FILE_u)) return
- call ESMF_TimeGet(nexttime, yy=yr_lilac, mm=mon_lilac, dd=day_lilac, s=tod_lilac, rc=rc)
+ rstwr = .true.
+ call ESMF_AlarmRingerOff( alarm, rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
- write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_lilac, mon_lilac, day_lilac, tod_lilac
+ else
+ rstwr = .false.
+ endif
+ if (masterproc) then
+ write(iulog,*)' restart alarm is ',rstwr
+ end if
- call t_startf ('ctsm_run')
- call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic=.false.)
- call t_stopf ('ctsm_run')
+ !--------------------------------
+ ! Run CTSM
+ !--------------------------------
- !--------------------------------
- ! Pack export state
- !--------------------------------
+ call t_barrierf('sync_ctsm_run1', mpicom)
- call t_startf ('lc_lnd_export')
- call export_fields(export_state, bounds, rc)
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- call t_stopf ('lc_lnd_export')
+ ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of
+ ! the timestep and is preferred for restart file names
+ ! TODO: is this correct for lilac?
- !--------------------------------
- ! Advance ctsm time step
- !--------------------------------
+ call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call ESMF_TimeGet(nexttime, yy=yr_lilac, mm=mon_lilac, dd=day_lilac, s=tod_lilac, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_lilac, mon_lilac, day_lilac, tod_lilac
- call advance_timestep()
+ call t_startf ('ctsm_run')
+ call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic=.false.)
+ call t_stopf ('ctsm_run')
- end do
+ !--------------------------------
+ ! Pack export state
+ !--------------------------------
+
+ call t_startf ('lc_lnd_export')
+ call export_fields(export_state, bounds, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call t_stopf ('lc_lnd_export')
+
+ !--------------------------------
+ ! Advance ctsm time step
+ !--------------------------------
+
+ call advance_timestep()
!--------------------------------
! Check that internal clock is in sync with lilac driver clock
diff --git a/src/cpl/nuopc/lnd_comp_nuopc.F90 b/src/cpl/nuopc/lnd_comp_nuopc.F90
index ed72ef801b..8ee6c2014e 100644
--- a/src/cpl/nuopc/lnd_comp_nuopc.F90
+++ b/src/cpl/nuopc/lnd_comp_nuopc.F90
@@ -743,7 +743,6 @@ subroutine ModelAdvance(gcomp, rc)
integer :: localPeCount ! Number of local Processors
logical :: rstwr ! .true. ==> write restart file before returning
logical :: nlend ! .true. ==> last time-step
- logical :: dosend ! true => send data back to driver
logical :: doalb ! .true. ==> do albedo calculation on this time step
real(r8) :: nextsw_cday ! calday from clock of next radiation computation
real(r8) :: caldayp1 ! ctsm calday plus dtime offset
@@ -819,112 +818,104 @@ subroutine ModelAdvance(gcomp, rc)
!--------------------------------
dtime = get_step_size()
- dosend = .false.
- do while(.not. dosend)
-
- ! TODO: This is currently hard-wired - is there a better way for nuopc?
- ! Note that the model clock is updated at the end of the time step not at the beginning
- nstep = get_nstep()
- if (nstep > 0) then
- dosend = .true.
- end if
-
- !--------------------------------
- ! Determine doalb based on nextsw_cday sent from atm model
- !--------------------------------
-
- caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.)
- if (nstep == 0) then
- doalb = .false.
- else if (nstep == 1) then
- doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8)
- else
- doalb = (nextsw_cday >= -0.5_r8)
- end if
- call update_rad_dtime(doalb)
+ ! TODO: This is currently hard-wired - is there a better way for nuopc?
+ ! Note that the model clock is updated at the end of the time step not at the beginning
+ nstep = get_nstep()
- !--------------------------------
- ! Determine if time to stop
- !--------------------------------
+ !--------------------------------
+ ! Determine doalb based on nextsw_cday sent from atm model
+ !--------------------------------
- call ESMF_ClockGetAlarm(clock, alarmname='alarm_stop', alarm=alarm, rc=rc)
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.)
- if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- nlend = .true.
- call ESMF_AlarmRingerOff( alarm, rc=rc )
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- else
- nlend = .false.
- endif
+ if (nstep == 1) then
+ doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8)
+ else
+ doalb = (nextsw_cday >= -0.5_r8)
+ end if
- !--------------------------------
- ! Determine if time to write restart
- !--------------------------------
- rstwr = .false.
- if (nlend .and. write_restart_at_endofrun) then
- rstwr = .true.
- else
- call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc)
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- if (ESMF_AlarmIsCreated(alarm, rc=rc)) then
- if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- rstwr = .true.
- call ESMF_AlarmRingerOff( alarm, rc=rc )
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- endif
- endif
- end if
+ call update_rad_dtime(doalb)
- !--------------------------------
- ! Run CTSM
- !--------------------------------
+ !--------------------------------
+ ! Determine if time to stop
+ !--------------------------------
- ! call ESMF_VMBarrier(vm, rc=rc)
- ! if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call ESMF_ClockGetAlarm(clock, alarmname='alarm_stop', alarm=alarm, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
- call t_startf ('shr_orb_decl')
- ! Note - the orbital inquiries set the values in clm_varorb via the module use statements
- call clm_orbital_update(clock, iulog, masterproc, eccen, obliqr, lambm0, mvelpp, rc)
+ if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
if (ChkErr(rc,__LINE__,u_FILE_u)) return
- calday = get_curr_calday(reuse_day_365_for_day_366=.true.)
- call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf )
- call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf )
- call t_stopf ('shr_orb_decl')
-
- call t_startf ('ctsm_run')
- ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of
- ! the timestep and is preferred for restart file names
- call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc)
+ nlend = .true.
+ call ESMF_AlarmRingerOff( alarm, rc=rc )
if (ChkErr(rc,__LINE__,u_FILE_u)) return
- call ESMF_TimeGet(nexttime, yy=yr_sync, mm=mon_sync, dd=day_sync, s=tod_sync, rc=rc)
+ else
+ nlend = .false.
+ endif
+
+ !--------------------------------
+ ! Determine if time to write restart
+ !--------------------------------
+ rstwr = .false.
+ if (nlend .and. write_restart_at_endofrun) then
+ rstwr = .true.
+ else
+ call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
- write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_sync, mon_sync, day_sync, tod_sync
- call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic)
- call t_stopf ('ctsm_run')
+ if (ESMF_AlarmIsCreated(alarm, rc=rc)) then
+ if (ESMF_AlarmIsRinging(alarm, rc=rc)) then
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ rstwr = .true.
+ call ESMF_AlarmRingerOff( alarm, rc=rc )
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ endif
+ endif
+ end if
- !--------------------------------
- ! Pack export state
- !--------------------------------
+ !--------------------------------
+ ! Run CTSM
+ !--------------------------------
- call t_startf ('lc_lnd_export')
- call export_fields(gcomp, bounds, glc_present, rof_prognostic, &
- water_inst%waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, rc)
- if (ChkErr(rc,__LINE__,u_FILE_u)) return
- call t_stopf ('lc_lnd_export')
+ ! call ESMF_VMBarrier(vm, rc=rc)
+ ! if (ChkErr(rc,__LINE__,u_FILE_u)) return
- !--------------------------------
- ! Advance ctsm time step
- !--------------------------------
+ call t_startf ('shr_orb_decl')
+ ! Note - the orbital inquiries set the values in clm_varorb via the module use statements
+ call clm_orbital_update(clock, iulog, masterproc, eccen, obliqr, lambm0, mvelpp, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ calday = get_curr_calday(reuse_day_365_for_day_366=.true.)
+ call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf )
+ call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf )
+ call t_stopf ('shr_orb_decl')
+
+ call t_startf ('ctsm_run')
+ ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of
+ ! the timestep and is preferred for restart file names
+ call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call ESMF_TimeGet(nexttime, yy=yr_sync, mm=mon_sync, dd=day_sync, s=tod_sync, rc=rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_sync, mon_sync, day_sync, tod_sync
+ call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic)
+ call t_stopf ('ctsm_run')
+
+ !--------------------------------
+ ! Pack export state
+ !--------------------------------
- call t_startf ('lc_ctsm2_adv_timestep')
- call advance_timestep()
- call t_stopf ('lc_ctsm2_adv_timestep')
+ call t_startf ('lc_lnd_export')
+ call export_fields(gcomp, bounds, glc_present, rof_prognostic, &
+ water_inst%waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, rc)
+ if (ChkErr(rc,__LINE__,u_FILE_u)) return
+ call t_stopf ('lc_lnd_export')
+
+ !--------------------------------
+ ! Advance ctsm time step
+ !--------------------------------
- end do
+ call t_startf ('lc_ctsm2_adv_timestep')
+ call advance_timestep()
+ call t_stopf ('lc_ctsm2_adv_timestep')
! Check that internal clock is in sync with master clock
! Note that the driver clock has not been updated yet - so at this point
diff --git a/src/main/clm_driver.F90 b/src/main/clm_driver.F90
index 454ff87463..f93143d9e3 100644
--- a/src/main/clm_driver.F90
+++ b/src/main/clm_driver.F90
@@ -1368,41 +1368,39 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro
! FIX(SPM, 082814) - in the fates branch RF and I commented out the if(.not.
! use_fates) then statement ... double check if this is required and why
- if (nstep > 0) then
- call t_startf('accum')
+ call t_startf('accum')
- call atm2lnd_inst%UpdateAccVars(bounds_proc)
+ call atm2lnd_inst%UpdateAccVars(bounds_proc)
- call temperature_inst%UpdateAccVars(bounds_proc, crop_inst)
+ call temperature_inst%UpdateAccVars(bounds_proc, crop_inst)
- call canopystate_inst%UpdateAccVars(bounds_proc)
+ call canopystate_inst%UpdateAccVars(bounds_proc)
- call water_inst%UpdateAccVars(bounds_proc)
+ call water_inst%UpdateAccVars(bounds_proc)
- call energyflux_inst%UpdateAccVars(bounds_proc)
+ call energyflux_inst%UpdateAccVars(bounds_proc)
- ! COMPILER_BUG(wjs, 2014-11-30, pgi 14.7) For pgi 14.7 to be happy when
- ! compiling this threaded, I needed to change the dummy arguments to be
- ! pointers, and get rid of the explicit bounds in the subroutine call.
- ! call bgc_vegetation_inst%UpdateAccVars(bounds_proc, &
- ! t_a10_patch=temperature_inst%t_a10_patch(bounds_proc%begp:bounds_proc%endp), &
- ! t_ref2m_patch=temperature_inst%t_ref2m_patch(bounds_proc%begp:bounds_proc%endp))
- call bgc_vegetation_inst%UpdateAccVars(bounds_proc, &
- t_a10_patch=temperature_inst%t_a10_patch, &
- t_ref2m_patch=temperature_inst%t_ref2m_patch)
+ ! COMPILER_BUG(wjs, 2014-11-30, pgi 14.7) For pgi 14.7 to be happy when
+ ! compiling this threaded, I needed to change the dummy arguments to be
+ ! pointers, and get rid of the explicit bounds in the subroutine call.
+ ! call bgc_vegetation_inst%UpdateAccVars(bounds_proc, &
+ ! t_a10_patch=temperature_inst%t_a10_patch(bounds_proc%begp:bounds_proc%endp), &
+ ! t_ref2m_patch=temperature_inst%t_ref2m_patch(bounds_proc%begp:bounds_proc%endp))
+ call bgc_vegetation_inst%UpdateAccVars(bounds_proc, &
+ t_a10_patch=temperature_inst%t_a10_patch, &
+ t_ref2m_patch=temperature_inst%t_ref2m_patch)
- if (use_crop) then
- call crop_inst%CropUpdateAccVars(bounds_proc, &
- temperature_inst%t_ref2m_patch, temperature_inst%t_soisno_col)
- end if
-
- if(use_fates) then
- call clm_fates%UpdateAccVars(bounds_proc)
- end if
+ if (use_crop) then
+ call crop_inst%CropUpdateAccVars(bounds_proc, &
+ temperature_inst%t_ref2m_patch, temperature_inst%t_soisno_col)
+ end if
- call t_stopf('accum')
+ if(use_fates) then
+ call clm_fates%UpdateAccVars(bounds_proc)
end if
+ call t_stopf('accum')
+
! ============================================================================
! Update history buffer
! ============================================================================
diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90
index c08fa2f961..cbb6e268f7 100644
--- a/src/main/histFileMod.F90
+++ b/src/main/histFileMod.F90
@@ -1171,6 +1171,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'
!-----------------------------------------------------------------------
@@ -1301,6 +1302,19 @@ subroutine htape_addfld (t, f, avgflag)
tape(t)%hlist(n)%avgflag = avgflag
end if
+ ! Override this tape's avgflag if nhtfrq == 1
+ if (tape(t)%nhtfrq == 1) then ! output is instantaneous
+ hist_avgflag_pertape(t) = 'I'
+ end if
+ ! Override this field's avgflag if the namelist or the previous line
+ ! has set this tape to
+ ! - instantaneous (I) or
+ ! - local time (L)
+ 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
!-----------------------------------------------------------------------
@@ -2658,7 +2672,7 @@ subroutine htape_timeconst3D(t, &
! !DESCRIPTION:
! Write time constant 3D variables to history tapes.
! Only write out when this subroutine is called (normally only for
- ! primary history files at very first time-step, nstep=0).
+ ! primary history files at very first time-step, nstep=1).
! Issue the required netcdf wrapper calls to define the history file
! contents.
!
@@ -3094,6 +3108,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
@@ -3353,8 +3368,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 (hist_avgflag_pertape(t) /= '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"
@@ -3362,11 +3387,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
!
@@ -3393,18 +3418,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 (hist_avgflag_pertape(t) /= '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)
@@ -3432,13 +3462,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 (hist_avgflag_pertape(t) /= '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)
@@ -4133,12 +4166,6 @@ subroutine hist_htapes_wrapup( rstwr, nlend, bounds, &
cycle
end if
- ! Skip nstep=0 if monthly average
-
- if (nstep==0 .and. tape(t)%nhtfrq==0) then
- cycle
- end if
-
! Determine if end of history interval
tape(t)%is_endhist = .false.
if (tape(t)%nhtfrq==0) then !monthly average
diff --git a/src/unit_test_shr/unittestTimeManagerMod.F90 b/src/unit_test_shr/unittestTimeManagerMod.F90
index 44109d5b86..8e1cdb3f36 100644
--- a/src/unit_test_shr/unittestTimeManagerMod.F90
+++ b/src/unit_test_shr/unittestTimeManagerMod.F90
@@ -177,9 +177,6 @@ subroutine unittest_timemgr_set_nstep(nstep)
! !DESCRIPTION:
! Set the time step number
!
- ! Note that the starting time step number is 0, so calling this with nstep = 1
- ! advances the time step beyond the starting time step.
- !
! !USES:
use clm_time_manager, only : advance_timestep
!
@@ -192,7 +189,7 @@ subroutine unittest_timemgr_set_nstep(nstep)
character(len=*), parameter :: subname = 'unittest_timemgr_set_nstep'
!-----------------------------------------------------------------------
- do n = 1, nstep
+ do n = 2, nstep
call advance_timestep()
end do
diff --git a/src/utils/AnnualFluxDribbler.F90 b/src/utils/AnnualFluxDribbler.F90
index c7a3b792fe..8ea854b904 100644
--- a/src/utils/AnnualFluxDribbler.F90
+++ b/src/utils/AnnualFluxDribbler.F90
@@ -258,7 +258,8 @@ subroutine set_curr_delta(this, bounds, delta)
do i = beg_index, end_index
this%amount_from_this_timestep(i) = delta(i)
end do
- if (.not. this%allows_non_annual_delta .and. .not. is_first_step()) then
+ ! is_first_step check no longer necessary since there is no nstep=0
+ if (.not. this%allows_non_annual_delta) then
do i = beg_index, end_index
if (this%amount_from_this_timestep(i) /= 0._r8) then
write(iulog,*) subname//' ERROR: found unexpected non-zero delta mid-year'
diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90
index 6ebd079c79..f606c2832b 100644
--- a/src/utils/clm_time_manager.F90
+++ b/src/utils/clm_time_manager.F90
@@ -178,6 +178,9 @@ end subroutine set_timemgr_init
!=========================================================================================
subroutine timemgr_init(curr_date_in )
+
+ use clm_varctl, only : nsrest, nsrContinue, nsrBranch
+
type(ESMF_Time), intent(in), optional :: curr_date_in
!---------------------------------------------------------------------------------
@@ -242,6 +245,11 @@ subroutine timemgr_init(curr_date_in )
tm_perp_date = TimeSetymd( perpetual_ymd, 0, "tm_perp_date" )
end if
+ ! Advance time step to start at nstep=1
+ if (nsrest /= nsrContinue .and. nsrest /= nsrBranch) then
+ call advance_timestep()
+ end if
+
! Print configuration summary to log file (stdout).
if (masterproc) call timemgr_print()
@@ -1725,7 +1733,7 @@ end function is_end_curr_year
logical function is_first_step()
!---------------------------------------------------------------------------------
- ! Return true on first step of initial run only.
+ ! Return true on first step of startup and hybrid runs.
! Local variables
character(len=*), parameter :: sub = 'clm::is_first_step'
@@ -1739,7 +1747,7 @@ logical function is_first_step()
call ESMF_ClockGet( tm_clock, advanceCount=step_no, rc=rc )
call chkrc(rc, sub//': error return from ESMF_ClockGet')
nstep = step_no
- is_first_step = (nstep == 0)
+ is_first_step = (nstep == 1)
end function is_first_step
!=========================================================================================
diff --git a/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf b/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf
index df8a59de4b..d2f984aa5b 100644
--- a/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf
+++ b/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf
@@ -276,7 +276,7 @@ contains
end subroutine getPrevYearfrac_leapYearAtYearBoundary_returnsCorrectValue
@Test
- subroutine getNstep_step0(this)
+ subroutine getNstep_step1(this)
class(TestTimeManager), intent(inout) :: this
integer :: nstep
@@ -284,8 +284,8 @@ contains
nstep = get_nstep()
- @assertEqual(0, nstep)
- end subroutine getNstep_step0
+ @assertEqual(1, nstep)
+ end subroutine getNstep_step1
@Test
subroutine getNstep_step3(this)
@@ -377,7 +377,7 @@ contains
call unittest_timemgr_setup(dtime=dtime_int)
- call set_nstep(1)
+ call set_nstep(2)
is_first = is_first_step()