From 5a3ae010cc7c7249170a49a3fb123b7527ea4065 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 25 Jun 2025 17:01:18 -0600 Subject: [PATCH 01/16] Add SUBSETDATAPOINT system test. Runs the subset_data point tool, then runs CTSM with the outputs. --- cime_config/SystemTests/subsetdatapoint.py | 88 ++++++++++++++++++++++ cime_config/config_tests.xml | 10 +++ cime_config/testdefs/testlist_clm.xml | 13 ++++ python/ctsm/run_sys_tests.py | 8 ++ 4 files changed, 119 insertions(+) create mode 100644 cime_config/SystemTests/subsetdatapoint.py diff --git a/cime_config/SystemTests/subsetdatapoint.py b/cime_config/SystemTests/subsetdatapoint.py new file mode 100644 index 0000000000..3633de8aad --- /dev/null +++ b/cime_config/SystemTests/subsetdatapoint.py @@ -0,0 +1,88 @@ +""" +CTSM-specific test that first runs the subset_data point tool and then ensures +that CTSM does not fail using the just-generated input files +""" + +import os +import sys +import logging +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.user_mod_support import apply_user_mods +from CIME.XML.standard_module_setup import * + +# In case we need to import subset_data later +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + +logger = logging.getLogger(__name__) + + +class SUBSETDATAPOINT(SystemTestsCommon): + def __init__(self, case): + """ + initialize an object interface to the SMS system test + """ + SystemTestsCommon.__init__(self, case) + + # Check the test setup + if not self._case.get_value("LND_GRID") == "CLM_USRDAT": + raise RuntimeError("SUBSETDATAPOINT tests require resolution CLM_USRDAT") + if "serial" not in self._case.get_value("MPILIB"): + raise RuntimeError("SUBSETDATAPOINT tests require a serial MPILIB") + if "BGC-CROP" not in self._case.get_value("COMPSET"): + raise RuntimeError("SUBSETDATAPOINT tests require a BGC-CROP compset") + + def build_phase(self, sharedlib_only=False, model_only=False): + + # Where the output files will be saved + out_dir = os.path.join(self._get_caseroot(), "subset_data_output") + usermods_dir = os.path.join(out_dir, "user_mods") + + # Import subset_data. Do it here rather than at top because otherwise the import will + # be attempted even during RUN phase. + # pylint: disable=wrong-import-position,import-outside-toplevel + from ctsm.subset_data import main as subset_data + + # Run the tool + lat = 45.402252 + lon = -92.798085 + sys.argv = [ + "tools/site_and_regional/subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--create-surface", + "--crop", + "--create-landuse", + "--surf-year", + "1850", + "--create-datm", + "--datm-syr", + "1901", + "--datm-eyr", + "1901", + "--create-user-mods", + "--outdir", + out_dir, + "--user-mods-dir", + usermods_dir, + "--overwrite", + ] + subset_data() + + # Required so that CTSM doesn't fail + user_nl_clm_path = os.path.join(usermods_dir, "user_nl_clm") + with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: + user_nl_clm.write("\ncheck_dynpft_consistency = .false.") + + # Apply the user mods + self._case.flush(flushall=True) + apply_user_mods(self._get_caseroot(), usermods_dir) + self._case.read_xml() + + # Do the build + super().build_phase(sharedlib_only, model_only) diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index ee80087a08..510f1f4c90 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -35,6 +35,16 @@ This defines various CTSM-specific system tests $STOP_N + + Run CTSM with files generated by the subset_data tool + 1 + FALSE + FALSE + never + $STOP_OPTION + $STOP_N + + CTSM Land model test to ensure that we can allocate and use a second grain pool 1 diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index ec10966594..9c73d35b90 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -4056,6 +4056,19 @@ + + + + + + + + + + + + + diff --git a/python/ctsm/run_sys_tests.py b/python/ctsm/run_sys_tests.py index 8108668246..66f38ad787 100644 --- a/python/ctsm/run_sys_tests.py +++ b/python/ctsm/run_sys_tests.py @@ -749,6 +749,14 @@ def _check_py_env(test_attributes): except ModuleNotFoundError as err: raise ModuleNotFoundError("modify_fsurdat" + err_msg) from err + # Check requirements for using subset_data Python module, if needed + subset_data_users = ["SUBSETDATAPOINT"] + if any(any(u in t for u in subset_data_users) for t in test_attributes): + try: + import ctsm.subset_data + except ModuleNotFoundError as err: + raise ModuleNotFoundError("subset_data" + err_msg) from err + # Check requirements for RXCROPMATURITY, if needed if any("RXCROPMATURITY" in t for t in test_attributes): try: From fb569f105e605dae2edbd91742bcc27204e2dc5b Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 30 Jun 2025 17:24:37 -0600 Subject: [PATCH 02/16] Refactor SUBSETDATAPOINT to use new SUBSETDATASHARED parent class. --- cime_config/SystemTests/subsetdata.py | 71 ++++++++++++++++++++++ cime_config/SystemTests/subsetdatapoint.py | 62 ++----------------- 2 files changed, 77 insertions(+), 56 deletions(-) create mode 100644 cime_config/SystemTests/subsetdata.py diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py new file mode 100644 index 0000000000..4065eb38e9 --- /dev/null +++ b/cime_config/SystemTests/subsetdata.py @@ -0,0 +1,71 @@ +""" +Parent class for CTSM-specific tests that first run the subset_data tool and then ensure +that CTSM does not fail using the just-generated input files +""" + +import os +import sys +import logging +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.user_mod_support import apply_user_mods +from CIME.XML.standard_module_setup import * + +# In case we need to import subset_data later +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + +logger = logging.getLogger(__name__) + + +class SUBSETDATASHARED(SystemTestsCommon): + def __init__(self, case, subset_data_cmd): + """ + initialize an object interface to the SMS system test + """ + SystemTestsCommon.__init__(self, case) + + # Check the test setup + if not self._case.get_value("LND_GRID") == "CLM_USRDAT": + raise RuntimeError("SUBSETDATA tests require resolution CLM_USRDAT") + if "serial" not in self._case.get_value("MPILIB"): + raise RuntimeError("SUBSETDATA tests require a serial MPILIB") + if "BGC-CROP" not in self._case.get_value("COMPSET"): + raise RuntimeError("SUBSETDATA tests require a BGC-CROP compset") + + # Add standard subset_data arguments + out_dir = os.path.join(self._get_caseroot(), "subset_data_output") + self.usermods_dir = os.path.join(out_dir, "user_mods") + self.subset_data_cmd = subset_data_cmd + [ + "--create-user-mods", + "--outdir", + out_dir, + "--user-mods-dir", + self.usermods_dir, + "--overwrite", + ] + + def build_phase(self, sharedlib_only=False, model_only=False): + + # Import subset_data. Do it here rather than at top because otherwise the import will + # be attempted even during RUN phase. + # pylint: disable=wrong-import-position,import-outside-toplevel + from ctsm.subset_data import main as subset_data + + # Run the tool + sys.argv = self.subset_data_cmd + subset_data() + + # Required so that CTSM doesn't fail + user_nl_clm_path = os.path.join(self.usermods_dir, "user_nl_clm") + with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: + user_nl_clm.write("\ncheck_dynpft_consistency = .false.") + + # Apply the user mods + self._case.flush(flushall=True) + apply_user_mods(self._get_caseroot(), self.usermods_dir) + self._case.read_xml() + + # Do the build + super().build_phase(sharedlib_only, model_only) diff --git a/cime_config/SystemTests/subsetdatapoint.py b/cime_config/SystemTests/subsetdatapoint.py index 3633de8aad..6b735809cd 100644 --- a/cime_config/SystemTests/subsetdatapoint.py +++ b/cime_config/SystemTests/subsetdatapoint.py @@ -3,52 +3,20 @@ that CTSM does not fail using the just-generated input files """ -import os -import sys -import logging -from CIME.SystemTests.system_tests_common import SystemTestsCommon -from CIME.user_mod_support import apply_user_mods -from CIME.XML.standard_module_setup import * +from subsetdata import SUBSETDATASHARED -# In case we need to import subset_data later -_CTSM_PYTHON = os.path.join( - os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" -) -sys.path.insert(1, _CTSM_PYTHON) -logger = logging.getLogger(__name__) - - -class SUBSETDATAPOINT(SystemTestsCommon): +class SUBSETDATAPOINT(SUBSETDATASHARED): def __init__(self, case): """ initialize an object interface to the SMS system test """ - SystemTestsCommon.__init__(self, case) - - # Check the test setup - if not self._case.get_value("LND_GRID") == "CLM_USRDAT": - raise RuntimeError("SUBSETDATAPOINT tests require resolution CLM_USRDAT") - if "serial" not in self._case.get_value("MPILIB"): - raise RuntimeError("SUBSETDATAPOINT tests require a serial MPILIB") - if "BGC-CROP" not in self._case.get_value("COMPSET"): - raise RuntimeError("SUBSETDATAPOINT tests require a BGC-CROP compset") - - def build_phase(self, sharedlib_only=False, model_only=False): - - # Where the output files will be saved - out_dir = os.path.join(self._get_caseroot(), "subset_data_output") - usermods_dir = os.path.join(out_dir, "user_mods") - # Import subset_data. Do it here rather than at top because otherwise the import will - # be attempted even during RUN phase. - # pylint: disable=wrong-import-position,import-outside-toplevel - from ctsm.subset_data import main as subset_data - - # Run the tool lat = 45.402252 lon = -92.798085 - sys.argv = [ + + # Don't need to include things that are added during SUBSETDATASHARED.__init__() + subset_data_cmd = [ "tools/site_and_regional/subset_data", "point", "--lat", @@ -65,24 +33,6 @@ def build_phase(self, sharedlib_only=False, model_only=False): "1901", "--datm-eyr", "1901", - "--create-user-mods", - "--outdir", - out_dir, - "--user-mods-dir", - usermods_dir, - "--overwrite", ] - subset_data() - - # Required so that CTSM doesn't fail - user_nl_clm_path = os.path.join(usermods_dir, "user_nl_clm") - with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: - user_nl_clm.write("\ncheck_dynpft_consistency = .false.") - - # Apply the user mods - self._case.flush(flushall=True) - apply_user_mods(self._get_caseroot(), usermods_dir) - self._case.read_xml() - # Do the build - super().build_phase(sharedlib_only, model_only) + super().__init__(case, subset_data_cmd) From c6c6cadc530c348dc3983f431f0e3febbfe1d410 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Tue, 1 Jul 2025 12:04:37 -0600 Subject: [PATCH 03/16] Add SUBSETDATAREGION SystemTest. Runs subset_data region tool to extract a six-gridcell region, then runs CTSM on the outputs. --- .gitmodules | 4 +- cime_config/SystemTests/subsetdata.py | 23 ++++++------ cime_config/SystemTests/subsetdataregion.py | 41 +++++++++++++++++++++ cime_config/config_tests.xml | 12 +++++- cime_config/testdefs/testlist_clm.xml | 18 ++++++++- components/cdeps | 2 +- python/ctsm/run_sys_tests.py | 2 +- src/dyn_subgrid/dynFileMod.F90 | 3 +- src/main/surfrdMod.F90 | 13 +++---- 9 files changed, 93 insertions(+), 25 deletions(-) create mode 100644 cime_config/SystemTests/subsetdataregion.py diff --git a/.gitmodules b/.gitmodules index 48bc074b92..ffe5937368 100644 --- a/.gitmodules +++ b/.gitmodules @@ -91,8 +91,8 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps -url = https://github.com/ESCOMP/CDEPS.git -fxtag = cdeps1.0.75 +url = https://github.com/samsrabin/CDEPS.git +fxtag = 304d112e23019579013d08e57a463334ac8cac8f # cx-length-filenames: Use CX-length filenames for all *_comp_nuopc.F90. fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py index 4065eb38e9..db4fe57010 100644 --- a/cime_config/SystemTests/subsetdata.py +++ b/cime_config/SystemTests/subsetdata.py @@ -53,19 +53,20 @@ def build_phase(self, sharedlib_only=False, model_only=False): # pylint: disable=wrong-import-position,import-outside-toplevel from ctsm.subset_data import main as subset_data - # Run the tool - sys.argv = self.subset_data_cmd - subset_data() + # Run the tool, if not already run, and apply usermods + if not os.path.exists(self.usermods_dir): + sys.argv = self.subset_data_cmd + subset_data() - # Required so that CTSM doesn't fail - user_nl_clm_path = os.path.join(self.usermods_dir, "user_nl_clm") - with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: - user_nl_clm.write("\ncheck_dynpft_consistency = .false.") + # Required so that CTSM doesn't fail + user_nl_clm_path = os.path.join(self.usermods_dir, "user_nl_clm") + with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: + user_nl_clm.write("\ncheck_dynpft_consistency = .false.\n") - # Apply the user mods - self._case.flush(flushall=True) - apply_user_mods(self._get_caseroot(), self.usermods_dir) - self._case.read_xml() + # Apply the user mods + self._case.flush(flushall=True) + apply_user_mods(self._get_caseroot(), self.usermods_dir) + self._case.read_xml() # Do the build super().build_phase(sharedlib_only, model_only) diff --git a/cime_config/SystemTests/subsetdataregion.py b/cime_config/SystemTests/subsetdataregion.py new file mode 100644 index 0000000000..e0c8144b3a --- /dev/null +++ b/cime_config/SystemTests/subsetdataregion.py @@ -0,0 +1,41 @@ +""" +CTSM-specific test that first runs the subset_data region tool and then ensures +that CTSM does not fail using the just-generated input files +""" + +from subsetdata import SUBSETDATASHARED + + +class SUBSETDATAREGION(SUBSETDATASHARED): + def __init__(self, case): + """ + initialize an object interface to the SMS system test + """ + + lat1 = -9 + lat2 = -7 + lon1 = 291 + lon2 = 293 + + # Don't need to include things that are added during SUBSETDATASHARED.__init__() + subset_data_cmd = [ + "tools/site_and_regional/subset_data", + "region", + "--lat1", + str(lat1), + "--lat2", + str(lat2), + "--lon1", + str(lon1), + "--lon2", + str(lon2), + "--create-mesh", + "--create-domain", + "--create-surface", + "--crop", + "--create-landuse", + "--surf-year", + "1850", + ] + + super().__init__(case, subset_data_cmd) diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index 510f1f4c90..7f2d17e9ab 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -36,7 +36,17 @@ This defines various CTSM-specific system tests - Run CTSM with files generated by the subset_data tool + Run CTSM with files generated by the subset_data point tool + 1 + FALSE + FALSE + never + $STOP_OPTION + $STOP_N + + + + Run CTSM with files generated by the subset_data region tool 1 FALSE FALSE diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 9c73d35b90..503fed514c 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -13,6 +13,7 @@ rxcropmaturity: Short tests to be run during development related to prescribed crop calendars matrixcn: Tests exercising the matrix-CN capability aux_clm_mpi_serial: aux_clm tests using mpi-serial. 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. + subset_data: Tests exercising the subset_data tool and running CTSM with its output --> @@ -4061,10 +4062,25 @@ + - + + + + + + + + + + + + + + + diff --git a/components/cdeps b/components/cdeps index 472264c96a..304d112e23 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 472264c96a14f9f97cbb087df2c2357c1dcea826 +Subproject commit 304d112e23019579013d08e57a463334ac8cac8f diff --git a/python/ctsm/run_sys_tests.py b/python/ctsm/run_sys_tests.py index 66f38ad787..e19bcd9b98 100644 --- a/python/ctsm/run_sys_tests.py +++ b/python/ctsm/run_sys_tests.py @@ -750,7 +750,7 @@ def _check_py_env(test_attributes): raise ModuleNotFoundError("modify_fsurdat" + err_msg) from err # Check requirements for using subset_data Python module, if needed - subset_data_users = ["SUBSETDATAPOINT"] + subset_data_users = ["SUBSETDATAPOINT", "SUBSETDATAREGION"] if any(any(u in t for u in subset_data_users) for t in test_attributes): try: import ctsm.subset_data diff --git a/src/dyn_subgrid/dynFileMod.F90 b/src/dyn_subgrid/dynFileMod.F90 index d7f22f9dcd..ecb2d111d9 100644 --- a/src/dyn_subgrid/dynFileMod.F90 +++ b/src/dyn_subgrid/dynFileMod.F90 @@ -7,6 +7,7 @@ module dynFileMod ! ! !USES: use shr_log_mod , only : errMsg => shr_log_errMsg + use clm_varctl , only : fname_len use dynTimeInfoMod , only : time_info_type, year_position_type use ncdio_pio , only : file_desc_t, ncd_pio_openfile, ncd_inqdid, ncd_inqdlen, ncd_io use abortutils , only : endrun @@ -56,7 +57,7 @@ type(dyn_file_type) function constructor(filename, year_position) type(year_position_type) , intent(in) :: year_position ! ! !LOCAL VARIABLES: - character(len=256) :: locfn ! local file name + character(len=fname_len) :: locfn ! local file name integer :: ier ! error code integer :: ntimes ! number of time samples integer :: varid ! netcdf variable ID diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90 index 4005ec7845..0e817fe0a6 100644 --- a/src/main/surfrdMod.F90 +++ b/src/main/surfrdMod.F90 @@ -15,6 +15,7 @@ module surfrdMod use clm_varcon , only : grlnd use clm_varctl , only : iulog use clm_varctl , only : use_cndv, use_crop, use_fates + use clm_varctl , only : fname_len use surfrdUtilsMod , only : check_sums_equal_1, apply_convert_ocean_to_land, collapse_crop_types use surfrdUtilsMod , only : collapse_to_dominant, collapse_crop_var, collapse_individual_lunits use ncdio_pio , only : file_desc_t, var_desc_t, ncd_pio_openfile, ncd_pio_closefile @@ -233,7 +234,7 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, lhillslope_file, actu character(len=*), intent(in) :: lhillslope_file ! hillslope dataset filename ! ! !LOCAL VARIABLES: - character(len=256):: locfn ! local file name + character(len=fname_len) :: locfn ! local file name integer, parameter :: n_dom_urban = 1 ! # of dominant urban landunits type(file_desc_t) :: ncid ! netcdf id for lfsurdat type(file_desc_t) :: ncid_hillslope ! netcdf id for lhillslope_file @@ -359,7 +360,7 @@ subroutine surfrd_get_num_patches (lfsurdat, actual_maxsoil_patches, actual_nump ! ! !LOCAL VARIABLES: - character(len=256):: locfn ! local file name + character(len=fname_len) :: locfn ! local file name type(file_desc_t) :: ncid ! netcdf file id integer :: dimid ! netCDF dimension id logical :: cft_dim_exists ! dimension exists on dataset @@ -427,7 +428,7 @@ subroutine surfrd_get_nlevurb (lfsurdat, actual_nlevurb) integer, intent(out) :: actual_nlevurb ! nlevurb from surface dataset ! ! !LOCAL VARIABLES: - character(len=256):: locfn ! local file name + character(len=fname_len) :: locfn ! local file name type(file_desc_t) :: ncid ! netcdf file id integer :: dimid ! netCDF dimension id character(len=32) :: subname = 'surfrd_get_nlevurb' ! subroutine name @@ -1153,7 +1154,6 @@ subroutine surfrd_lakemask(begg, endg) ! !USES: use clm_instur , only : pct_lake_max use dynSubgridControlMod , only : get_flanduse_timeseries - use clm_varctl , only : fname_len use fileutils , only : getfil ! ! !ARGUMENTS: @@ -1162,7 +1162,7 @@ subroutine surfrd_lakemask(begg, endg) ! ! !LOCAL VARIABLES: type(file_desc_t) :: ncid_dynuse ! netcdf id for landuse timeseries file - character(len=256) :: locfn ! local file name + character(len=fname_len) :: locfn ! local file name character(len=fname_len) :: fdynuse ! landuse.timeseries filename logical :: readvar ! @@ -1208,7 +1208,6 @@ subroutine surfrd_urbanmask(begg, endg) ! !USES: use clm_instur , only : pct_urban_max use dynSubgridControlMod , only : get_flanduse_timeseries - use clm_varctl , only : fname_len use fileutils , only : getfil ! ! !ARGUMENTS: @@ -1217,7 +1216,7 @@ subroutine surfrd_urbanmask(begg, endg) ! ! !LOCAL VARIABLES: type(file_desc_t) :: ncid_dynuse ! netcdf id for landuse timeseries file - character(len=256) :: locfn ! local file name + character(len=fname_len) :: locfn ! local file name character(len=fname_len) :: fdynuse ! landuse.timeseries filename logical :: readvar ! From 4575931a83ef12f95cb6cc799d9058e8dcad9877 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 09:48:36 -0600 Subject: [PATCH 04/16] Use self.build_indv() instead of super.build_phase(). This seems to be the standard practice. --- cime_config/SystemTests/subsetdata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py index db4fe57010..c7be11e5bd 100644 --- a/cime_config/SystemTests/subsetdata.py +++ b/cime_config/SystemTests/subsetdata.py @@ -69,4 +69,4 @@ def build_phase(self, sharedlib_only=False, model_only=False): self._case.read_xml() # Do the build - super().build_phase(sharedlib_only, model_only) + self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only) From dfffcdb85b000065b9c46d9b10bd23b4854a1b69 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 09:53:02 -0600 Subject: [PATCH 05/16] Check if sharedlib_only rather than for existence of subset_data outputs. build_phase gets called twice: - once with sharedlib_only = True and - once with model_only = True Because we only need subset_data run once, we only do it for the sharedlib_only call. We had originally checked for the existence of the subset_data outputs, but that might lead to a situation where the user expects subset_data to be called but it's not. Better to run unnecessarily (e.g., if you fixed some FORTRAN code and just need to rebuild). --- cime_config/SystemTests/subsetdata.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py index c7be11e5bd..894c565f87 100644 --- a/cime_config/SystemTests/subsetdata.py +++ b/cime_config/SystemTests/subsetdata.py @@ -47,14 +47,24 @@ def __init__(self, case, subset_data_cmd): ] def build_phase(self, sharedlib_only=False, model_only=False): + """ + Run subset_data and then build the model + """ # Import subset_data. Do it here rather than at top because otherwise the import will # be attempted even during RUN phase. # pylint: disable=wrong-import-position,import-outside-toplevel from ctsm.subset_data import main as subset_data - # Run the tool, if not already run, and apply usermods - if not os.path.exists(self.usermods_dir): + # Run subset_data. + # build_phase gets called twice: + # - once with sharedlib_only = True and + # - once with model_only = True + # Because we only need subset_data run once, we only do it for the sharedlib_only call. + # We could also check for the existence of the subset_data outputs, but that might lead to + # a situation where the user expects subset_data to be called but it's not. Better to run + # unnecessarily (e.g., if you fixed some FORTRAN code and just need to rebuild). + if not sharedlib_only: sys.argv = self.subset_data_cmd subset_data() From c7458b8e4e6bad8c4a73546dcaf18d9b10b672ad Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 11:33:59 -0600 Subject: [PATCH 06/16] CDEPS: Merge in cdeps1.0.77 --- .gitmodules | 2 +- components/cdeps | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 27ab2134a3..b5f1ddbc34 100644 --- a/.gitmodules +++ b/.gitmodules @@ -92,7 +92,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps url = https://github.com/samsrabin/CDEPS.git -fxtag = 304d112e23019579013d08e57a463334ac8cac8f # cx-length-filenames: Use CX-length filenames for all *_comp_nuopc.F90. +fxtag = 732abf339299e65658a5b627f53c10b7fc6def67 # cx-length-filenames: Merge tag 'cdeps1.0.77' into cx-length-filenames fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/components/cdeps b/components/cdeps index 304d112e23..732abf3392 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 304d112e23019579013d08e57a463334ac8cac8f +Subproject commit 732abf339299e65658a5b627f53c10b7fc6def67 From 139c876a1008a9f574d7827ffccea55b799c15cb Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 12:10:30 -0600 Subject: [PATCH 07/16] Run subset_data if outputs don't exist. It seems like build_phase() gets called at least once before sharedlib_only=True, because before this commit I was getting this error: ERROR: Command /glade/work/samrabin/ctsm_subsetdata-systemtest/bld/build-namelist failed rc=255 out= err=Attempt to call undefined import method with arguments ("main") via package "CLMBuildNamelist" (Perhaps you forgot to load the package?) at /glade/work/samrabin/ctsm_subsetdata-systemtest/bld/build-namelist line 21. ERROR : CLM build-namelist::CLMBuildNamelist::add_default() : No default value found for fsurdat. Are defaults provided for this resolution and land mask? --- cime_config/SystemTests/subsetdata.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py index 894c565f87..23897611dc 100644 --- a/cime_config/SystemTests/subsetdata.py +++ b/cime_config/SystemTests/subsetdata.py @@ -64,7 +64,8 @@ def build_phase(self, sharedlib_only=False, model_only=False): # We could also check for the existence of the subset_data outputs, but that might lead to # a situation where the user expects subset_data to be called but it's not. Better to run # unnecessarily (e.g., if you fixed some FORTRAN code and just need to rebuild). - if not sharedlib_only: + # If the subset_data outputs don't exist, though, run regardless of what phase we're in. + if not sharedlib_only or not os.path.exists(self.usermods_dir): sys.argv = self.subset_data_cmd subset_data() From b026d0c03125b3fbec94f21dcd506d09658c261f Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 12:16:51 -0600 Subject: [PATCH 08/16] CDEPS: Delete DATAMODELTEST test. --- .gitmodules | 2 +- components/cdeps | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index b5f1ddbc34..29212517b6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -92,7 +92,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps url = https://github.com/samsrabin/CDEPS.git -fxtag = 732abf339299e65658a5b627f53c10b7fc6def67 # cx-length-filenames: Merge tag 'cdeps1.0.77' into cx-length-filenames +fxtag = 786ccc3a14cfb5730aff1086251c039b438eb8be # cx-length-filenames: Delete DATAMODELTEST test fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/components/cdeps b/components/cdeps index 732abf3392..786ccc3a14 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 732abf339299e65658a5b627f53c10b7fc6def67 +Subproject commit 786ccc3a14cfb5730aff1086251c039b438eb8be From 1022b000d1b18cdd9540be0460bf6d182a33f4d6 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 12:19:12 -0600 Subject: [PATCH 09/16] Fix subset_data call condition. --- cime_config/SystemTests/subsetdata.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py index 23897611dc..e94a058e7c 100644 --- a/cime_config/SystemTests/subsetdata.py +++ b/cime_config/SystemTests/subsetdata.py @@ -64,8 +64,7 @@ def build_phase(self, sharedlib_only=False, model_only=False): # We could also check for the existence of the subset_data outputs, but that might lead to # a situation where the user expects subset_data to be called but it's not. Better to run # unnecessarily (e.g., if you fixed some FORTRAN code and just need to rebuild). - # If the subset_data outputs don't exist, though, run regardless of what phase we're in. - if not sharedlib_only or not os.path.exists(self.usermods_dir): + if sharedlib_only: sys.argv = self.subset_data_cmd subset_data() From 03cd0dc529f7287c399f3dd0f7b15d730e289c8b Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Mon, 7 Jul 2025 13:03:46 -0600 Subject: [PATCH 10/16] CDEPS: More CX-length nlfilename and streamfilename. --- .gitmodules | 2 +- components/cdeps | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 29212517b6..e35efe5b0d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -92,7 +92,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps url = https://github.com/samsrabin/CDEPS.git -fxtag = 786ccc3a14cfb5730aff1086251c039b438eb8be # cx-length-filenames: Delete DATAMODELTEST test +fxtag = 0595593400cae8dd65f50a13d9167fb248be9dfb # cx-length-filenames: More CX-length nlfilename and streamfilename. fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/components/cdeps b/components/cdeps index 786ccc3a14..0595593400 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 786ccc3a14cfb5730aff1086251c039b438eb8be +Subproject commit 0595593400cae8dd65f50a13d9167fb248be9dfb From 0e14784f41d34508dbf5b84ffacfd8c04cafdda5 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 9 Jul 2025 10:40:00 -0600 Subject: [PATCH 11/16] CDEPS: Use cdeps1.0.78 with 512-char PR merged. --- .gitmodules | 4 ++-- components/cdeps | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index e35efe5b0d..bd883f3613 100644 --- a/.gitmodules +++ b/.gitmodules @@ -91,8 +91,8 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps -url = https://github.com/samsrabin/CDEPS.git -fxtag = 0595593400cae8dd65f50a13d9167fb248be9dfb # cx-length-filenames: More CX-length nlfilename and streamfilename. +url = https://github.com/ESCOMP/CDEPS.git +fxtag = cdeps1.0.78 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/components/cdeps b/components/cdeps index 0595593400..2544107383 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 0595593400cae8dd65f50a13d9167fb248be9dfb +Subproject commit 2544107383aa1428154b66f0bf35a0acac6b7e22 From e3f88557c552661d2d7bd190db10e288d7dac35a Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 9 Jul 2025 15:58:09 -0600 Subject: [PATCH 12/16] CIME: Move case.cmpgen_namelists call to _sharedlib_build_phase This was causing failure in SETUP phase when generating baselines for the SUBSETDATA SystemTests. --- .gitmodules | 4 ++-- cime | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index bd883f3613..f69068730a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -75,8 +75,8 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime -url = https://github.com/ESMCI/cime -fxtag = cime6.1.102 +url = https://github.com/samsrabin/cime_myfork +fxtag = d51a2de004b32817148ef1a3af4e8cd5e3740edf fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/cime diff --git a/cime b/cime index 1006c39f59..d51a2de004 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit 1006c39f59577d47994fb3fb897566b2b8fa12ed +Subproject commit d51a2de004b32817148ef1a3af4e8cd5e3740edf From 0d0393893e6727fa9612afbbc9d8ea114b6d6bb3 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 8 Aug 2025 15:24:26 -0600 Subject: [PATCH 13/16] SUBSETDATA: Add redundant script call for safety. --- cime_config/SystemTests/subsetdata.py | 52 ++++++++++++++++++--------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/cime_config/SystemTests/subsetdata.py b/cime_config/SystemTests/subsetdata.py index e94a058e7c..6861030b04 100644 --- a/cime_config/SystemTests/subsetdata.py +++ b/cime_config/SystemTests/subsetdata.py @@ -46,16 +46,20 @@ def __init__(self, case, subset_data_cmd): "--overwrite", ] + # Run subset_data, if needed. + # It's needed during SETUP and/or NLCOMP phases if comparing/generating a baseline because + # the namelist comparison will require generating a namelist, and that will fail if we + # haven't specified our custom fsurdat and other stuff. By calling self._run_subset_data() + # only if the usermods directory doesn't yet exist, we avoid it being called every time the + # test class is initialized (which happens, e.g., in RUN phase). + # if not os.path.exists(self.usermods_dir): + # self._run_subset_data() + def build_phase(self, sharedlib_only=False, model_only=False): """ Run subset_data and then build the model """ - # Import subset_data. Do it here rather than at top because otherwise the import will - # be attempted even during RUN phase. - # pylint: disable=wrong-import-position,import-outside-toplevel - from ctsm.subset_data import main as subset_data - # Run subset_data. # build_phase gets called twice: # - once with sharedlib_only = True and @@ -64,19 +68,33 @@ def build_phase(self, sharedlib_only=False, model_only=False): # We could also check for the existence of the subset_data outputs, but that might lead to # a situation where the user expects subset_data to be called but it's not. Better to run # unnecessarily (e.g., if you fixed some FORTRAN code and just need to rebuild). + # In that same vein, yes we did run subset_data during the first time this test case was + # initialized (see __init__() above), but we're doing it again here just to be safe. if sharedlib_only: - sys.argv = self.subset_data_cmd - subset_data() - - # Required so that CTSM doesn't fail - user_nl_clm_path = os.path.join(self.usermods_dir, "user_nl_clm") - with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: - user_nl_clm.write("\ncheck_dynpft_consistency = .false.\n") - - # Apply the user mods - self._case.flush(flushall=True) - apply_user_mods(self._get_caseroot(), self.usermods_dir) - self._case.read_xml() + self._run_subset_data() # Do the build self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only) + + def _run_subset_data(self): + """ + Run subset_data + """ + # Import subset_data. Do it here rather than at top because otherwise the import will + # be attempted even during RUN phase. + # pylint: disable=wrong-import-position,import-outside-toplevel + from ctsm.subset_data import main as subset_data + + # Run subset_data + sys.argv = self.subset_data_cmd + subset_data() + + # Required so that CTSM doesn't fail + user_nl_clm_path = os.path.join(self.usermods_dir, "user_nl_clm") + with open(user_nl_clm_path, "a", encoding="utf-8") as user_nl_clm: + user_nl_clm.write("\ncheck_dynpft_consistency = .false.\n") + + # Apply the user mods + self._case.flush(flushall=True) + apply_user_mods(self._get_caseroot(), self.usermods_dir) + self._case.read_xml() From d8bf1b84b868ec3fa90e1b3d01338c925e55120e Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 8 Aug 2025 15:26:24 -0600 Subject: [PATCH 14/16] CIME: Fix behavior of --skip-tests-with-existing-baselines. --- .gitmodules | 2 +- cime | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f69068730a..349fad64f6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -76,7 +76,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime url = https://github.com/samsrabin/cime_myfork -fxtag = d51a2de004b32817148ef1a3af4e8cd5e3740edf +fxtag = fb48c08a80560c029a9df556746bda2245611ad7 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/cime diff --git a/cime b/cime index d51a2de004..fb48c08a80 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit d51a2de004b32817148ef1a3af4e8cd5e3740edf +Subproject commit fb48c08a80560c029a9df556746bda2245611ad7 From e16d2733e33ac1a7af87e7c83d53fb8bbc4962ad Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Fri, 8 Aug 2025 15:31:38 -0600 Subject: [PATCH 15/16] CIME: Use cime6.1.112. --- .gitmodules | 4 ++-- cime | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index bf4590d5a7..ba76bf816a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -75,8 +75,8 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime -url = https://github.com/samsrabin/cime_myfork -fxtag = fb48c08a80560c029a9df556746bda2245611ad7 +url = https://github.com/ESMCI/cime +fxtag = cime6.1.112 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/cime diff --git a/cime b/cime index fb48c08a80..6fb4e9e1a3 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit fb48c08a80560c029a9df556746bda2245611ad7 +Subproject commit 6fb4e9e1a3bcb72f9251fc86b90660fc59f7da12 From c5798059eacf70cf6050cb5b3ff8aea5725e39b6 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Tue, 12 Aug 2025 09:58:40 -0600 Subject: [PATCH 16/16] Update ChangeLog/Sum. --- doc/ChangeLog | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ doc/ChangeSum | 1 + 2 files changed, 74 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 52d853c436..df709ebd94 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,77 @@ =============================================================== +Tag name: ctsm5.3.069 +Originator(s): samrabin (Sam Rabin, UCAR/TSS) +Date: Tue Aug 12 09:52:59 MDT 2025 +One-line Summary: Add SystemTests to run subset_data and then CTSM + +Purpose and description of changes +---------------------------------- + +Adds SUBSETDATAPOINT and SUBSETDATAREGION tests to aux_clm (and new subset_data suite). These run subset_data for either a point or a six-cell region, then run CTSM with the outputs. + + +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.) + +[ ] clm6_0 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description): +- Resolves [Issue #1491: Add two new tests that run subset_data and then run a case from it](https://github.com/ESCOMP/CTSM/issues/1491) + + +Notes of particular relevance for developers: +--------------------------------------------- +NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + +Changes to tests or testing: +- Adds test SUBSETDATAPOINT_Ld5_D_Mmpi-serial.CLM_USRDAT.I2000Clm60BgcCropCrujra.derecho_intel.clm-default +- Adds test SUBSETDATAREGION_Ld5_D_Mmpi-serial.CLM_USRDAT.I2000Clm60BgcCropCrujra.derecho_intel.clm-default +- Adds new subset_data suite with those tests in it +- Those tests are also in aux_clm + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - Unit, black, and pylint checks pass. Two system tests fail due to recent conda and mamba updates on Derecho; these have been fixed on b4b-dev with [Pull Request #3403: Fix py_env_create and tests by samsrabin](https://github.com/ESCOMP/CTSM/pull/3403) + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- [Pull Request #3292: ctsm5.3.069: Add SystemTests to run subset_data and then CTSM by samsrabin](https://github.com/ESCOMP/CTSM/pull/3292) + +=============================================================== +=============================================================== Tag name: ctsm5.3.068 Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) Date: Mon 11 Aug 2025 02:27:39 PM MDT diff --git a/doc/ChangeSum b/doc/ChangeSum index 442484253a..33389e00c5 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.3.069 samrabin 08/12/2025 Add SystemTests to run subset_data and then CTSM ctsm5.3.068 slevis 08/11/2025 Change megan_use_gamma_sm to default false ctsm5.3.067 samrabin 08/08/2025 (Mostly) fix interim restarts ctsm5.3.066 slevis 08/08/2025 Merge b4b-dev to master