From d9f75e9f41631c98d3268bb2d600c414c86120d0 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 4 Apr 2026 14:05:23 -0600 Subject: [PATCH 01/39] Set defaults for DATM_CPLHIST_* settings for 1850 with DATM coupled to CLM --- datm/cime_config/config_component.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 8c91d7fe2..3bff174e8 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -204,6 +204,9 @@ char UNSET + + $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm + run_component_datm env_run.xml directory for coupler history data mode (only used for when DATM_MODE is CPLHIST) @@ -213,6 +216,9 @@ char UNSET + + CAM7CLM6_cesm30alpha08c_ne30pg3_1850 + run_component_datm env_run.xml case name used to determine stream filenames when DATM_MODE is CPLHIST @@ -228,6 +234,7 @@ 1 1 1 + 1 1895 1901 1901 @@ -277,6 +284,7 @@ 1901 1901 0 + 1 2000 1972 1948 @@ -339,6 +347,7 @@ 1920 1920 -1 + 3 2004 2004 1972 From 67a8f18c82efe81679e30c1867577b9c8cb50fdb Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 4 Apr 2026 14:14:49 -0600 Subject: [PATCH 02/39] Make the default setting for DATM_CPLHIST_DIR under the users archive directory location for the DATM_CPLHIST_CASE under cpl/hist subdirectory --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 3bff174e8..34ec75d0b 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -203,7 +203,7 @@ char - UNSET + $CIME_OUTPUT_ROOT/archive/$DATM_CPLHIST_CASE/cpl/hist $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm From fcb28adce89a36b0de6855bf3e7371bbb7ded9e5 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 4 Apr 2026 14:30:45 -0600 Subject: [PATCH 03/39] Correct the filenames for cplhist mode for PRES_NDEP --- datm/cime_config/stream_definition_datm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index c7460c200..eb77586f0 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -5238,7 +5238,7 @@ $ATM_DOMAIN_MESH - $DATM_CPLHIST_DIR/$DATM_CPLHIST_CASE.cpl.ha2x1d.%ym.nc + $DATM_CPLHIST_DIR/$DATM_CPLHIST_CASE.cpl.hx.atm.24h.avrg.%ymd-00000.nc a2x1d_Faxa_ndep Faxa_ndep From a72518b9c2782df1b3459ff492c9f622513e538a Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 4 Apr 2026 20:44:18 -0600 Subject: [PATCH 04/39] Add clim_1850_cesm3_for_cmip7 --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 34ec75d0b..8dfe25253 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -104,7 +104,7 @@ char - none,clim_1850_cmip7,clim_2000_cmip7,clim_2010_cmip7,hist_cmip7,clim_1850_cmip6,clim_2000_cmip6,clim_2010_cmip6,hist_cmip6,SSP1-2.6,SSP2-4.5,SSP3-7.0,SSP5-3.4,SSP5-8.5,cplhist + none,clim_1850_cesm3_for_cmip7,clim_1850_cmip7,clim_2000_cmip7,clim_2010_cmip7,hist_cmip7,clim_1850_cmip6,clim_2000_cmip6,clim_2010_cmip6,hist_cmip6,SSP1-2.6,SSP2-4.5,SSP3-7.0,SSP5-3.4,SSP5-8.5,cplhist clim_2000 clim_1850_cmip6 From b6ebc5c8fd6b244987d63be81dd9b08bd8302092 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 4 Apr 2026 20:50:06 -0600 Subject: [PATCH 05/39] Add clim_1850_cesm3_for_cmip7 --- datm/cime_config/stream_definition_datm.xml | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index eb77586f0..ef0b0a0e4 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -4891,6 +4891,46 @@ single + + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc + + + $DIN_LOC_ROOT/atm/cam/chem/trop_strat_mam5_ts4_aero_spinup/ndep/fndep_clm_B1850C_MT4s.1850monthly.ne30_c251220.nc + + + + NDEP_NHx_month Faxa_ndep_nhx + NDEP_NOy_month Faxa_ndep_noy + + + null + + bilinear + + null + 1 + 1850 + 1850 + 0 + + linear + + + cycle + + + 1.5 + + single + + $DIN_LOC_ROOT/share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc From ab6e2d7693bf29704fe48f0252f800e8d4a1de2f Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 4 Apr 2026 21:00:02 -0600 Subject: [PATCH 06/39] CPLHIST settings for CLM should be just CLM60, to preserve older answers --- datm/cime_config/config_component.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 8dfe25253..58729753e 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -174,6 +174,7 @@ SSP4-6.0 SSP5-3.4 SSP5-8.5 + cmip7_20tr cmip6_20tr cmip6_20tr omip.iaf @@ -205,7 +206,7 @@ $CIME_OUTPUT_ROOT/archive/$DATM_CPLHIST_CASE/cpl/hist - $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm + $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm run_component_datm env_run.xml @@ -217,7 +218,7 @@ UNSET - CAM7CLM6_cesm30alpha08c_ne30pg3_1850 + CAM7CLM6_cesm30alpha08c_ne30pg3_1850 run_component_datm env_run.xml @@ -234,7 +235,7 @@ 1 1 1 - 1 + 1 1895 1901 1901 @@ -284,7 +285,7 @@ 1901 1901 0 - 1 + 1 2000 1972 1948 @@ -347,7 +348,7 @@ 1920 1920 -1 - 3 + 3 2004 2004 1972 From 07b976f7281d9194a96bd450eb621409bd92b2ae Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 19 Aug 2026 09:42:00 -0600 Subject: [PATCH 07/39] Needed to get the right variables for ndep in cplhist mode --- datm/cime_config/stream_definition_datm.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index 6a5bf0669..334b4bcbd 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -5314,7 +5314,8 @@ $DATM_CPLHIST_DIR/$DATM_CPLHIST_CASE.cpl.hx.atm.24h.avrg.%ymd-00000.nc - a2x1d_Faxa_ndep Faxa_ndep + atmImp_Faxa_ndep1 Faxa_ndep_nhx + atmImp_Faxa_ndep2 Faxa_ndep_noy null From 2e0473f5ae63aec719193cb1663a4c4506678c31 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 19 Aug 2026 15:37:18 -0600 Subject: [PATCH 08/39] Spin off some functions to modularize the code, to make way for adding more --- datm/cime_config/buildnml | 89 +++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index e81cdb55e..68bdb745b 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -90,6 +90,56 @@ def _get_neon_data_availability(case, neonsite): return None +def _handle_pts_mode( case, config ): + if case.get_value('PTS_LON'): + scol_lon = float(case.get_value('PTS_LON')) + else: + scol_lon = -999. + if case.get_value('PTS_LAT'): + scol_lat = float(case.get_value('PTS_LAT')) + else: + scol_lat = -999. + if case.get_value('PTS_DOMAINFILE'): + if scol_lon > -999. and scol_lat > -999. and case.get_value("PTS_DOMAINFILE") != "UNSET": + config['single_column'] = 'true' + else: + config['single_column'] = 'false' + +def _handle_model_grid(case, config, available_neon_data): + model_grid = case.get_value("GRID") + if 'CLM_USRDAT' in model_grid: + config['model_grid'] = 'CLM_USRDAT' + if 'NEON' in clm_usrdat_name: + neonsite = case.get_value("NEONSITE") + config['neonsite'] = neonsite + if neonsite: + config['neon'] = "True" + # download and use the listing.csv file to determine data availablity + available_neon_data = _get_neon_data_availability(case, neonsite) + if 'PLUMBER2' in clm_usrdat_name: + plumber2site = case.get_value('PLUMBER2SITE') + config['plumber2site'] = plumber2site + if plumber2site: + config['plumber'] = "True" + else: + config['model_grid'] = model_grid + +def _error_check_cplhist_mode(case, config): + + check_cplhist = False + if "cplhist" in config['datm_mode']: + check_cplhist = True + if "cplhist" in case.get_value("DATM_CO2_TSERIES"): + check_cplhist = True + if "cplhist" in case.get_value("DATM_PRESAERO"): + check_cplhist = True + if "cplhist" in case.get_value("DATM_PRESNDEP"): + check_cplhist = True + if "cplhist" in case.get_value("DATM_PRESO3"): + check_cplhist = True + if "cplhist" in case.get_value("DATM_TOPO"): + check_cplhist = True + # pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements #################################################################################### def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path): @@ -115,7 +165,6 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") datm_co2_tseries = case.get_value("DATM_CO2_TSERIES") atm_grid = case.get_value("ATM_GRID") - model_grid = case.get_value("GRID") comp_lnd = case.get_value("COMP_LND") compset = case.get_value("COMPSET") @@ -142,21 +191,9 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path # Initialize namelist defaults config = {} + available_neon_data = None - if 'CLM_USRDAT' in model_grid: - config['model_grid'] = 'CLM_USRDAT' - if 'NEON' in clm_usrdat_name: - neonsite = case.get_value("NEONSITE") - if neonsite: - config['neon'] = "True" - # download and use the listing.csv file to determine data availablity - available_neon_data = _get_neon_data_availability(case, neonsite) - if 'PLUMBER2' in clm_usrdat_name: - plumber2site = case.get_value('PLUMBER2SITE') - if plumber2site: - config['plumber'] = "True" - else: - config['model_grid'] = model_grid + _handle_model_grid(case, config, available_neon_data) config['datm_mode'] = datm_mode config['datm_co2_tseries'] = datm_co2_tseries @@ -165,19 +202,9 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path config['datm_preso3'] = datm_preso3 config['clm_usrdat_name'] = clm_usrdat_name - if case.get_value('PTS_LON'): - scol_lon = float(case.get_value('PTS_LON')) - else: - scol_lon = -999. - if case.get_value('PTS_LAT'): - scol_lat = float(case.get_value('PTS_LAT')) - else: - scol_lat = -999. - if case.get_value('PTS_DOMAINFILE'): - if scol_lon > -999. and scol_lat > -999. and case.get_value("PTS_DOMAINFILE") != "UNSET": - config['single_column'] = 'true' - else: - config['single_column'] = 'false' + _handle_pts_mode( case, config ) + + _error_check_cplhist_mode(case, config) nmlgen.init_defaults(infile, config) @@ -211,11 +238,11 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path if datm_co2_tseries != "none": streamlist.append("co2tseries.{}".format(datm_co2_tseries)) if clm_usrdat_name == 'NEON.PRISM': - streamlist.append(clm_usrdat_name+"_PRECIP."+neonsite) + streamlist.append(clm_usrdat_name+"_PRECIP."+config['neonsite']) if clm_usrdat_name == 'NEON': - streamlist.append(clm_usrdat_name+".NEON_PRECIP."+neonsite) + streamlist.append(clm_usrdat_name+".NEON_PRECIP."+config['neonsite']) if clm_usrdat_name == 'PLUMBER2': - streamlist.append(clm_usrdat_name+"."+plumber2site) + streamlist.append(clm_usrdat_name+"."+config['plumber2site']) bias_correct = nmlgen.get_value("bias_correct") if bias_correct is not None: From 6fb38a9bcb7477322860e65923118608689e4932 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 19 Aug 2026 16:28:31 -0600 Subject: [PATCH 09/39] Add headers to new functions, and do suggestions from co-pilots review including important points about clm_usr_dat_name and available_neon_data --- datm/cime_config/buildnml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 68bdb745b..6c85636ab 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -89,8 +89,11 @@ def _get_neon_data_availability(case, neonsite): expect(newestdate, "No tower data found on server for NEON site {}".format(neonsite)) return None - +#################################################################################### def _handle_pts_mode( case, config ): +#################################################################################### + """ Handle PTS mode settings for single column runs. If PTS_LON and PTS_LAT are set, then set single_column to true. + """ if case.get_value('PTS_LON'): scol_lon = float(case.get_value('PTS_LON')) else: @@ -105,10 +108,16 @@ def _handle_pts_mode( case, config ): else: config['single_column'] = 'false' -def _handle_model_grid(case, config, available_neon_data): +#################################################################################### +def _handle_model_grid(case, config): +#################################################################################### + """ Handle model grid and particular settings for it for NEON and PLUMBER2 cases + """ + available_neon_data = None model_grid = case.get_value("GRID") if 'CLM_USRDAT' in model_grid: config['model_grid'] = 'CLM_USRDAT' + clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") if 'NEON' in clm_usrdat_name: neonsite = case.get_value("NEONSITE") config['neonsite'] = neonsite @@ -123,8 +132,16 @@ def _handle_model_grid(case, config, available_neon_data): config['plumber'] = "True" else: config['model_grid'] = model_grid + return available_neon_data +#################################################################################### def _error_check_cplhist_mode(case, config): +#################################################################################### + """ Error checks for cplhist mode. + Make sure needed settings are set when used. + Make sure directories expected exist + Make sure it works for all the different cplhist options + """ check_cplhist = False if "cplhist" in config['datm_mode']: @@ -192,8 +209,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path # Initialize namelist defaults config = {} - available_neon_data = None - _handle_model_grid(case, config, available_neon_data) + available_neon_data = _handle_model_grid(case, config) config['datm_mode'] = datm_mode config['datm_co2_tseries'] = datm_co2_tseries From 2523ab1645bad1004b5a7851ad21e192b5b42497 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 20 Aug 2026 01:17:07 -0600 Subject: [PATCH 10/39] Do error checking for CPLHIST mode, this resolves #399 --- datm/cime_config/buildnml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 6c85636ab..f620aae24 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -157,6 +157,22 @@ def _error_check_cplhist_mode(case, config): if "cplhist" in case.get_value("DATM_TOPO"): check_cplhist = True + if check_cplhist: + cplhist_dir = case.get_value("DATM_CPLHIST_DIR") + cplhist_case = case.get_value("DATM_CPLHIST_CASE") + cplhist_domain = case.get_value("DATM_CPLHIST_DOMAIN_FILE") + expect(cplhist_case is not None, "DATM_CPLHIST_CASE must be set when using cplhist mode") + expect(cplhist_case != "UNSET", "DATM_CPLHIST_CASE must be set when using cplhist mode") + expect(cplhist_dir is not None, "DATM_CPLHIST_DIR must be set when using cplhist mode") + expect(os.path.isdir(cplhist_dir), "DATM_CPLHIST_DIR {} does not exist".format(cplhist_dir)) + if cplhist_domain != "null": + expect(os.path.isfile(cplhist_domain), "DATM_CPLHIST_DOMAIN_FILE {} does not exist".format(cplhist_domain)) + else: + cplhist_domain = case.get_value("DATM_CPLHIST_DOMAIN_FILE") + expect(cplhist_domain == "null", "DATM_CPLHIST_DOMAIN_FILE can only be set when using cplhist mode") + cplhist_case = case.get_value("DATM_CPLHIST_CASE") + expect(cplhist_case == "UNSET", "DATM_CPLHIST_CASE should only be set when using cplhist mode") + # pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements #################################################################################### def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path): From 3f51f391b6d826f2b2bab1fb3bbabdeac3aba716 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 20 Aug 2026 01:21:48 -0600 Subject: [PATCH 11/39] Let 1850 cases with CLM60 use cmip7_20tr for CO2 timeseries --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 3761d3599..f0522ce37 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -174,7 +174,7 @@ SSP4-6.0 SSP5-3.4 SSP5-8.5 - cmip7_20tr + cmip7_20tr cmip6_20tr cmip6_20tr omip.iaf From 7842d5adbfb0c02eb00d2f5f9ca9b712910d42a5 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 20 Aug 2026 11:36:32 -0600 Subject: [PATCH 12/39] Missing for PTS_LAT/LON was actually -999.99 so set it to a variable and use it to define it, and also check that if one is set the other is as well, and then ensure single_column is set at the end of the subroutine --- datm/cime_config/buildnml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index f620aae24..2763d80b1 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -94,20 +94,30 @@ def _handle_pts_mode( case, config ): #################################################################################### """ Handle PTS mode settings for single column runs. If PTS_LON and PTS_LAT are set, then set single_column to true. """ + missing = -999.99 if case.get_value('PTS_LON'): scol_lon = float(case.get_value('PTS_LON')) else: - scol_lon = -999. + scol_lon = missing if case.get_value('PTS_LAT'): scol_lat = float(case.get_value('PTS_LAT')) else: - scol_lat = -999. + scol_lat = missing if case.get_value('PTS_DOMAINFILE'): - if scol_lon > -999. and scol_lat > -999. and case.get_value("PTS_DOMAINFILE") != "UNSET": + if scol_lon > missing and scol_lat > missing and case.get_value("PTS_DOMAINFILE") != "UNSET": config['single_column'] = 'true' else: config['single_column'] = 'false' + # Check that if either PTS_LON/PTS_LAT is set the other is as well + # TODO: NOTE: This should really be in CMEPS + print( scol_lon, scol_lat ) + if (scol_lon != missing and scol_lat == missing) or (scol_lon == missing and scol_lat != missing): + expect(False, "If either PTS_LON or PTS_LAT is set, the other must be set as well") + + # Verify that the expected output setting was actually done + expect(config['single_column'] is not None, "single_column should have been set in this subroutine") + #################################################################################### def _handle_model_grid(case, config): #################################################################################### From 00dbb60fcfbd7591581b12f0d3fe17218aa18650 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 20 Aug 2026 14:32:50 -0600 Subject: [PATCH 13/39] Add some output expects for _handle_model_grid especially for the NEON and PLUMBER2 settings --- datm/cime_config/buildnml | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 2763d80b1..2d4edef95 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -125,9 +125,11 @@ def _handle_model_grid(case, config): """ available_neon_data = None model_grid = case.get_value("GRID") + clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") if 'CLM_USRDAT' in model_grid: config['model_grid'] = 'CLM_USRDAT' - clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") + # If CLM_USRDAT is being used, CLM_USRDAT_NAME must be set + expect(clm_usrdat_name is not None, "CLM_USRDAT_NAME must be set when using CLM_USRDAT grid") if 'NEON' in clm_usrdat_name: neonsite = case.get_value("NEONSITE") config['neonsite'] = neonsite @@ -141,7 +143,38 @@ def _handle_model_grid(case, config): if plumber2site: config['plumber'] = "True" else: + expect(clm_usrdat_name == "UNSET", "CLM_USRDAT_NAME must NOT be set when NOT using a CLM_USRDAT grid") config['model_grid'] = model_grid + + # Ensure output settings are done as expected + expect(config['model_grid'] is not None, "model_grid should have been set in this subroutine") + if "NEON" in clm_usrdat_name: + expect(config['neon'] == "True", "neon should have been set in this subroutine, since NEON is on") + expect(config['neonsite'] is not None, "neonsite should have been set in this subroutine, since NEON is on") + expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because NEON is on") + else: + expect(available_neon_data is None, "available_neon_data should NOT be set if NEON is off") + expect(case.get_value('NEONSITE') == "", "NEONSITE should NOT have been set in this subroutine, since NEON is off") + expect(not 'neonsite' in config, "neonsite should have NOT been set in this subroutine, since NEON is off") + expect(not 'neon' in config, "neonshould have NOT been set in this subroutine, since NEON is off") + + missing_yr_filename = 9999 + if "PLUMBER2" in clm_usrdat_name: + expect(config['plumber2site'] is not None, "plumber2site should have been set in this subroutine") + expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because PLUMBER2 is on") + expect(config['plumber'] == "True", "plumber should have been set in this subroutine, since PLUMBER2 is on") + datm_mode = case.get_value("DATM_MODE") + if ( datm_mode == "CLM1PT" ): + expect(case.get_value('DATM_YR_START_FILENAME') != missing_yr_filename, "DATM_YR_START_FILENAME should have been set, since PLUMBER2 on") + expect(case.get_value('DATM_YR_END_FILENAME') != missing_yr_filename, "DATM_YR_END_FILENAME should have been set, since PLUMBER2 on") + else: + expect(case.get_value('PLUMBER2SITE') == "", "PLUMBER2SITE should NOT have been set in this subroutine, since PLUMBER2 is off") + expect(case.get_value('DATM_YR_START_FILENAME') == missing_yr_filename, "DATM_YR_START_FILENAME should NOT have been set, since PLUMBER2 is off") + expect(case.get_value('DATM_YR_END_FILENAME') == missing_yr_filename, "DATM_YR_END_FILENAME should NOT have been set, since PLUMBER2 is off") + expect(not 'plumber2site' in config, "plumber2site should have NOT been set in this subroutine, since PLUMBER2 is off") + expect(not 'plumber' in config, "plumber should have NOT been set in this subroutine, since PLUMBER2 is off") + + # Return the data available for NEON return available_neon_data #################################################################################### From 03abec7f455b29d82f2e96de94ff050224ea316a Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 20 Aug 2026 14:40:54 -0600 Subject: [PATCH 14/39] Set the default case for CPLHIST with 1850 and CLM60 to a recent case that can be used --- datm/cime_config/config_component.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index f0522ce37..733b2cafe 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -219,7 +219,7 @@ UNSET - CAM7CLM6_cesm30alpha08c_ne30pg3_1850 + b.e30_alpha08o.B1850C_MTso.ne30_t232_wgx3.330 run_component_datm env_run.xml @@ -286,7 +286,7 @@ 1901 1901 0 - 1 + 101 2000 1972 1948 @@ -358,7 +358,7 @@ 1920 1920 -1 - 3 + 101 2004 2004 1972 From 3dd89dbbbf1f986f9405d90d6700f439840e7bae Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 20 Aug 2026 15:43:07 -0600 Subject: [PATCH 15/39] No longer need to set DATM_PRESNDEP for CPLHIST case --- .../testdefs/testmods_dirs/datm/cplhist/shell_commands | 1 - 1 file changed, 1 deletion(-) diff --git a/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands b/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands index 847d5514e..40a91d274 100644 --- a/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands +++ b/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands @@ -3,4 +3,3 @@ ./xmlchange DATM_YR_START="101" ./xmlchange DATM_YR_END="101" ./xmlchange RUN_STARTDATE="0101-01-01" -./xmlchange DATM_PRESNDEP="clim_1850_cmip6" From b1aaf1347988a33c1ad73f910de439e8c6ac081c Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 11:33:25 -0600 Subject: [PATCH 16/39] Have to add logic depending on the LND model since some variables are only available when coupled to CLM --- datm/cime_config/buildnml | 72 ++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 2d4edef95..5b8ac7a45 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -125,7 +125,8 @@ def _handle_model_grid(case, config): """ available_neon_data = None model_grid = case.get_value("GRID") - clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") + comp_lnd = case.get_value("COMP_LND") + clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") # NOTE: Will be None if not coupled to CLM if 'CLM_USRDAT' in model_grid: config['model_grid'] = 'CLM_USRDAT' # If CLM_USRDAT is being used, CLM_USRDAT_NAME must be set @@ -143,36 +144,53 @@ def _handle_model_grid(case, config): if plumber2site: config['plumber'] = "True" else: - expect(clm_usrdat_name == "UNSET", "CLM_USRDAT_NAME must NOT be set when NOT using a CLM_USRDAT grid") config['model_grid'] = model_grid + if comp_lnd != "clm": + expect(clm_usrdat_name is None, "CLM_USRDAT_NAME is not expected to exist when the land model is NOT CLM") + expect(available_neon_data is None, "available_neon_data should NOT be set when the land model is NOT CLM") + expect(not 'neonsite' in config, "neonsite should have NOT been set when the land model is NOT CLM") + expect(not 'neon' in config, "neon should have NOT been set when the land model is NOT CLM") + expect(not 'plumber2site' in config, "plumber2site should have NOT been set when the land model is NOT CLM") + expect(not 'plumber' in config, "plumber should have NOT been set when the land model is NOT CLM") + else: + expect(clm_usrdat_name == "UNSET", "CLM_USRDAT_NAME must NOT be set when NOT using a CLM_USRDAT grid") + # # Ensure output settings are done as expected + # expect(config['model_grid'] is not None, "model_grid should have been set in this subroutine") - if "NEON" in clm_usrdat_name: - expect(config['neon'] == "True", "neon should have been set in this subroutine, since NEON is on") - expect(config['neonsite'] is not None, "neonsite should have been set in this subroutine, since NEON is on") - expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because NEON is on") - else: - expect(available_neon_data is None, "available_neon_data should NOT be set if NEON is off") - expect(case.get_value('NEONSITE') == "", "NEONSITE should NOT have been set in this subroutine, since NEON is off") - expect(not 'neonsite' in config, "neonsite should have NOT been set in this subroutine, since NEON is off") - expect(not 'neon' in config, "neonshould have NOT been set in this subroutine, since NEON is off") - - missing_yr_filename = 9999 - if "PLUMBER2" in clm_usrdat_name: - expect(config['plumber2site'] is not None, "plumber2site should have been set in this subroutine") - expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because PLUMBER2 is on") - expect(config['plumber'] == "True", "plumber should have been set in this subroutine, since PLUMBER2 is on") - datm_mode = case.get_value("DATM_MODE") - if ( datm_mode == "CLM1PT" ): - expect(case.get_value('DATM_YR_START_FILENAME') != missing_yr_filename, "DATM_YR_START_FILENAME should have been set, since PLUMBER2 on") - expect(case.get_value('DATM_YR_END_FILENAME') != missing_yr_filename, "DATM_YR_END_FILENAME should have been set, since PLUMBER2 on") - else: - expect(case.get_value('PLUMBER2SITE') == "", "PLUMBER2SITE should NOT have been set in this subroutine, since PLUMBER2 is off") - expect(case.get_value('DATM_YR_START_FILENAME') == missing_yr_filename, "DATM_YR_START_FILENAME should NOT have been set, since PLUMBER2 is off") - expect(case.get_value('DATM_YR_END_FILENAME') == missing_yr_filename, "DATM_YR_END_FILENAME should NOT have been set, since PLUMBER2 is off") - expect(not 'plumber2site' in config, "plumber2site should have NOT been set in this subroutine, since PLUMBER2 is off") - expect(not 'plumber' in config, "plumber should have NOT been set in this subroutine, since PLUMBER2 is off") + + # + # Check for expected settings when coupled to CLM for NEON and PLUMBER2 cases + # + if comp_lnd == "clm": + if "NEON" in clm_usrdat_name: + expect(config['neon'] == "True", "neon should have been set in this subroutine, since NEON is on") + expect(config['neonsite'] is not None, "neonsite should have been set in this subroutine, since NEON is on") + expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because NEON is on") + else: + expect(available_neon_data is None, "available_neon_data should NOT be set if NEON is off") + expect(case.get_value('NEONSITE') == "", "NEONSITE should NOT have been set in this subroutine, since NEON is off") + expect(not 'neonsite' in config, "neonsite should have NOT been set in this subroutine, since NEON is off") + expect(not 'neon' in config, "neon should have NOT been set in this subroutine, since NEON is off") + + missing_yr_filename = 9999 + if "PLUMBER2" in clm_usrdat_name: + expect(config['plumber2site'] is not None, "plumber2site should have been set in this subroutine") + expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because PLUMBER2 is on") + expect(config['plumber'] == "True", "plumber should have been set in this subroutine, since PLUMBER2 is on") + datm_mode = case.get_value("DATM_MODE") + if ( datm_mode == "CLM1PT" ): + expect(case.get_value('DATM_YR_START_FILENAME') != missing_yr_filename, "DATM_YR_START_FILENAME should have been set, since PLUMBER2 on") + expect(case.get_value('DATM_YR_END_FILENAME') != missing_yr_filename, "DATM_YR_END_FILENAME should have been set, since PLUMBER2 on") + else: + expect(case.get_value('DATM_YR_START_FILENAME') == missing_yr_filename, "DATM_YR_START_FILENAME should NOT have been set, since PLUMBER2 is off") + expect(case.get_value('DATM_YR_END_FILENAME') == missing_yr_filename, "DATM_YR_END_FILENAME should NOT have been set, since PLUMBER2 is off") + + else: + expect(case.get_value('PLUMBER2SITE') == "", "PLUMBER2SITE should NOT have been set in this subroutine, since PLUMBER2 is off") + expect(not 'plumber2site' in config, "plumber2site should have NOT been set in this subroutine, since PLUMBER2 is off") + expect(not 'plumber' in config, "plumber should have NOT been set in this subroutine, since PLUMBER2 is off") # Return the data available for NEON return available_neon_data From 1a200c970808602fea2934ed9848e8c0026328e7 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 13:31:41 -0600 Subject: [PATCH 17/39] Remove debug print statement that shouldn't be there --- datm/cime_config/buildnml | 1 - 1 file changed, 1 deletion(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 5b8ac7a45..a3a3a7f87 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -111,7 +111,6 @@ def _handle_pts_mode( case, config ): # Check that if either PTS_LON/PTS_LAT is set the other is as well # TODO: NOTE: This should really be in CMEPS - print( scol_lon, scol_lat ) if (scol_lon != missing and scol_lat == missing) or (scol_lon == missing and scol_lat != missing): expect(False, "If either PTS_LON or PTS_LAT is set, the other must be set as well") From 9b3b5a68d48d52437b564232f3379826f4d0e827 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 13:35:43 -0600 Subject: [PATCH 18/39] Make align, start, end for the CPLHIST default consistently 101 --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 733b2cafe..322f6c773 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -236,7 +236,7 @@ 1 1 1 - 1 + 101 1895 1901 1901 From 7faa9cdf78828f0a055ebe85ab829a7879e7af53 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 17:57:06 -0600 Subject: [PATCH 19/39] Update CO2 dataset fixing #410 --- datm/cime_config/stream_definition_datm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index 334b4bcbd..a3b33ea31 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -3788,7 +3788,7 @@ none - $DIN_LOC_ROOT/atm/datm7/CO2/co2_input4MIPs_GHGConcentrations_CMIP_CR-CMIP-1-0-0_gm_1750-2022_CMIP7_c20250228.nc + $DIN_LOC_ROOT/atm/datm7/CO2/co2_input4MIPs_GHGConcentrations_CMIP_CR-CMIP-1-0-0_gm_1750-2022_CMIP7_c20260601.nc co2 Sa_co2diag From 0aef11e8af34ff3c36588401c10f02d939bfc4ac Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 17:59:47 -0600 Subject: [PATCH 20/39] Set the ndep default file for 1850 to the preliminary one --- datm/cime_config/config_component.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 322f6c773..4bd5d6827 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -108,6 +108,7 @@ clim_2000 clim_1850_cmip6 + clim_1850_cesm3_for_cmip7 clim_2000_cmip6 clim_2010_cmip6 hist_cmip6 From 9e731667a0d565a39558955603d1dbe50befab72 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 18:02:09 -0600 Subject: [PATCH 21/39] Backout setting CO2 to cmip7_20tr until we have clim_cmip7_1850 options --- datm/cime_config/config_component.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 4bd5d6827..b5c8cc0f3 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -175,7 +175,6 @@ SSP4-6.0 SSP5-3.4 SSP5-8.5 - cmip7_20tr cmip6_20tr cmip6_20tr omip.iaf From b03bd5b8042a6df3f6630d20d06d31aa66f05239 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 21 Aug 2026 18:39:15 -0600 Subject: [PATCH 22/39] Only thing needed now is to the start the run start year, the others are in the defaults for CPLHIST --- .../testdefs/testmods_dirs/datm/cplhist/shell_commands | 4 ---- 1 file changed, 4 deletions(-) diff --git a/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands b/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands index 40a91d274..cf1fb2576 100644 --- a/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands +++ b/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands @@ -1,5 +1 @@ -./xmlchange DATM_CPLHIST_DIR='$DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm' -./xmlchange DATM_CPLHIST_CASE="b.e30_alpha08o.B1850C_MTso.ne30_t232_wgx3.330" -./xmlchange DATM_YR_START="101" -./xmlchange DATM_YR_END="101" ./xmlchange RUN_STARTDATE="0101-01-01" From ca485b541be0cd4b5eaeec18338fab4745e8517e Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Mon, 24 Aug 2026 18:19:26 -0600 Subject: [PATCH 23/39] Restrict setting of cplhist for DATM_CO2_TSERIES to only if DATM%CPLHIST and CLM, add a note that this needs to be coordinated with the CTSM and MOM env variables --- datm/cime_config/config_component.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index b5c8cc0f3..a0c9796ad 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -179,11 +179,15 @@ cmip6_20tr omip.iaf omip.jra - cplhist + cplhist run_component_datm env_run.xml - DATM CO2 time series + DATM CO2 time series + NOTE: This needs to be coordinated with CCSM_BGC in CMEPS, and wtih either the ocean or land model + For CLM coordinate it with the CLM_CO2_TYPE variable + For MOM coordinate it with the OCN_CO2_TYPE variable + From ec8c0a18ae92d842914fa5a5abd1b5d28cd38eba Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Tue, 25 Aug 2026 11:33:15 -0600 Subject: [PATCH 24/39] Remove cplhist testmod as realized in code review --- datm/cime_config/testdefs/testlist_datm.xml | 2 +- .../testdefs/testmods_dirs/datm/cplhist/shell_commands | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands diff --git a/datm/cime_config/testdefs/testlist_datm.xml b/datm/cime_config/testdefs/testlist_datm.xml index 361c38b7d..168dd7d67 100644 --- a/datm/cime_config/testdefs/testlist_datm.xml +++ b/datm/cime_config/testdefs/testlist_datm.xml @@ -43,7 +43,7 @@ - + diff --git a/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands b/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands deleted file mode 100644 index cf1fb2576..000000000 --- a/datm/cime_config/testdefs/testmods_dirs/datm/cplhist/shell_commands +++ /dev/null @@ -1 +0,0 @@ -./xmlchange RUN_STARTDATE="0101-01-01" From 8106de78384d84b2101d42ef5bbb65199bcf4c36 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Tue, 25 Aug 2026 11:35:10 -0600 Subject: [PATCH 25/39] Set YR_ALIGN for CPLHIST to 1, as the normal thing is to start with year 1 for CPLHIST spinup cases --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index a0c9796ad..fe02aea5e 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -240,7 +240,7 @@ 1 1 1 - 101 + 1 1895 1901 1901 From 816b01f11e06fa65c19142a750daef10d2a18130 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Tue, 25 Aug 2026 12:03:07 -0600 Subject: [PATCH 26/39] Fix XML syntax error --- datm/cime_config/testdefs/testlist_datm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/testdefs/testlist_datm.xml b/datm/cime_config/testdefs/testlist_datm.xml index 168dd7d67..580d8b49e 100644 --- a/datm/cime_config/testdefs/testlist_datm.xml +++ b/datm/cime_config/testdefs/testlist_datm.xml @@ -43,7 +43,7 @@ - From 967ef1f3928ae27c8f08b1f5d84d8ea32dda5715 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 11:41:12 -0600 Subject: [PATCH 27/39] Simple changes from code review adding more to docstrings, and combining two expect statements into one --- datm/cime_config/buildnml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index a3a3a7f87..ea31685e2 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -92,7 +92,7 @@ def _get_neon_data_availability(case, neonsite): #################################################################################### def _handle_pts_mode( case, config ): #################################################################################### - """ Handle PTS mode settings for single column runs. If PTS_LON and PTS_LAT are set, then set single_column to true. + """ Handle PTS mode settings for single column runs. If PTS_LON and PTS_LAT are set, then set config[single_column] to true. """ missing = -999.99 if case.get_value('PTS_LON'): @@ -120,7 +120,20 @@ def _handle_pts_mode( case, config ): #################################################################################### def _handle_model_grid(case, config): #################################################################################### - """ Handle model grid and particular settings for it for NEON and PLUMBER2 cases + """ Set config['model grid'] always + Also do some checking and set needed variables for a CLM user defined grid. + For a CLM single-point/regional case (CLM user defined grid) + Set config['model_grid'] to CLM_USRDAT to signify this + For a NEON case + set config['neonsite'] + config['neon'] is True + For a PLUMBER2 case + set config['plumber2site'] + config['plumber2'] is True + + Will fail if settings aren't setup as expected + + Returns an empty list normally; for a NEON case it returns the list of available NEON data """ available_neon_data = None model_grid = case.get_value("GRID") @@ -221,8 +234,7 @@ def _error_check_cplhist_mode(case, config): cplhist_dir = case.get_value("DATM_CPLHIST_DIR") cplhist_case = case.get_value("DATM_CPLHIST_CASE") cplhist_domain = case.get_value("DATM_CPLHIST_DOMAIN_FILE") - expect(cplhist_case is not None, "DATM_CPLHIST_CASE must be set when using cplhist mode") - expect(cplhist_case != "UNSET", "DATM_CPLHIST_CASE must be set when using cplhist mode") + expect(cplhist_case is not None and cplhist_case != UNSET, "DATM_CPLHIST_CASE must be set when using cplhist mode") expect(cplhist_dir is not None, "DATM_CPLHIST_DIR must be set when using cplhist mode") expect(os.path.isdir(cplhist_dir), "DATM_CPLHIST_DIR {} does not exist".format(cplhist_dir)) if cplhist_domain != "null": From 339bf37adebc0567fe6f37618961644b70af5dba Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 14:35:51 -0600 Subject: [PATCH 28/39] Update datm/cime_config/config_component.xml From review for consistency. Co-authored-by: Bill Sacks --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index fe02aea5e..8a09914a5 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -211,7 +211,7 @@ $CIME_OUTPUT_ROOT/archive/$DATM_CPLHIST_CASE/cpl/hist - $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm + $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm run_component_datm env_run.xml From 458df474bf7457c1bec1c76b5bf84e915c71397c Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 14:37:04 -0600 Subject: [PATCH 29/39] Update datm/cime_config/config_component.xml Another review suggestion for consistency in RE. Co-authored-by: Bill Sacks --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 8a09914a5..e39bb298c 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -223,7 +223,7 @@ UNSET - b.e30_alpha08o.B1850C_MTso.ne30_t232_wgx3.330 + b.e30_alpha08o.B1850C_MTso.ne30_t232_wgx3.330 run_component_datm env_run.xml From 56a9e5ec73061d176b427a357766dec13e3ae69b Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 17:01:17 -0600 Subject: [PATCH 30/39] Update datm/cime_config/config_component.xml From review make RE more consistent. Co-authored-by: Bill Sacks --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index e39bb298c..4f65504bd 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -362,7 +362,7 @@ 1920 1920 -1 - 101 + 101 2004 2004 1972 From 4d0489a8a8ad672e8cd6ae7f69361208683a475b Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 17:01:57 -0600 Subject: [PATCH 31/39] Update datm/cime_config/config_component.xml RE consistency Co-authored-by: Bill Sacks --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 4f65504bd..21310c604 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -290,7 +290,7 @@ 1901 1901 0 - 101 + 101 2000 1972 1948 From 10832477569d688a76cab709609aaa21271daf58 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 17:02:36 -0600 Subject: [PATCH 32/39] Update datm/cime_config/config_component.xml RE consistency. Co-authored-by: Bill Sacks --- datm/cime_config/config_component.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 21310c604..f6afd20d5 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -240,7 +240,7 @@ 1 1 1 - 1 + 1 1895 1901 1901 From 7d611892fc49bc660290ce13a81a38b11bd11053 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 17:05:39 -0600 Subject: [PATCH 33/39] A couple things caught in the code review, fix a typo, and remove a commented section of XML --- datm/cime_config/config_component.xml | 2 +- datm/cime_config/stream_definition_datm.xml | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index fe02aea5e..ed4f493d7 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -184,7 +184,7 @@ run_component_datm env_run.xml DATM CO2 time series - NOTE: This needs to be coordinated with CCSM_BGC in CMEPS, and wtih either the ocean or land model + NOTE: This needs to be coordinated with CCSM_BGC in CMEPS, and with either the ocean or land model For CLM coordinate it with the CLM_CO2_TYPE variable For MOM coordinate it with the OCN_CO2_TYPE variable diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index a3b33ea31..fef04c14f 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -4935,13 +4935,6 @@ NDEP_NHx_month Faxa_ndep_nhx NDEP_NOy_month Faxa_ndep_noy - null From 18c23f1792590f3eac73ea22cc9340924f9795ca Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 17:18:16 -0600 Subject: [PATCH 34/39] More things from review, remove checking if DATM_CPLHIST_DOMAIN_FILE exists as that's covered in check_input_data, add some comments around the check for the DATM_CPLHIST_DIR and also show the variable unresolved so it shows what variables it's built with --- datm/cime_config/buildnml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index ea31685e2..0ef6da931 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -234,11 +234,14 @@ def _error_check_cplhist_mode(case, config): cplhist_dir = case.get_value("DATM_CPLHIST_DIR") cplhist_case = case.get_value("DATM_CPLHIST_CASE") cplhist_domain = case.get_value("DATM_CPLHIST_DOMAIN_FILE") - expect(cplhist_case is not None and cplhist_case != UNSET, "DATM_CPLHIST_CASE must be set when using cplhist mode") + expect(cplhist_case is not None or cplhist_case != UNSET, "DATM_CPLHIST_CASE must be set when using cplhist mode") expect(cplhist_dir is not None, "DATM_CPLHIST_DIR must be set when using cplhist mode") - expect(os.path.isdir(cplhist_dir), "DATM_CPLHIST_DIR {} does not exist".format(cplhist_dir)) - if cplhist_domain != "null": - expect(os.path.isfile(cplhist_domain), "DATM_CPLHIST_DOMAIN_FILE {} does not exist".format(cplhist_domain)) + # Check that the CPLHIST directory exists + # This is a little unusual in buildnml, as the check_input_data will make sure the files exist + # But, most often the problem is that I'm pointing to the wrong directory, so seeing that the directory + # doesn't exist is easier than showing all of the myriad of files that are missing later + unres_cplhist_dir = case.get_value("DATM_CPLHIST_DIR", resolved=False) + expect(os.path.isdir(cplhist_dir), "DATM_CPLHIST_DIR {} does not exist (directory with input variables is {})".format(cplhist_dir, unres_cplhist_dir)) else: cplhist_domain = case.get_value("DATM_CPLHIST_DOMAIN_FILE") expect(cplhist_domain == "null", "DATM_CPLHIST_DOMAIN_FILE can only be set when using cplhist mode") From 07846d8321d7cf8f1efe4f53dc7f3b46de0d56b7 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 26 Aug 2026 17:21:23 -0600 Subject: [PATCH 35/39] Fix expect so that PLUMBER2 sites work --- datm/cime_config/buildnml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/buildnml b/datm/cime_config/buildnml index 0ef6da931..51716e8db 100755 --- a/datm/cime_config/buildnml +++ b/datm/cime_config/buildnml @@ -192,7 +192,7 @@ def _handle_model_grid(case, config): expect(config['model_grid'] == "CLM_USRDAT", "model_grid should have been set to CLM_USRDAT because PLUMBER2 is on") expect(config['plumber'] == "True", "plumber should have been set in this subroutine, since PLUMBER2 is on") datm_mode = case.get_value("DATM_MODE") - if ( datm_mode == "CLM1PT" ): + if ( datm_mode == "1PT" ): expect(case.get_value('DATM_YR_START_FILENAME') != missing_yr_filename, "DATM_YR_START_FILENAME should have been set, since PLUMBER2 on") expect(case.get_value('DATM_YR_END_FILENAME') != missing_yr_filename, "DATM_YR_END_FILENAME should have been set, since PLUMBER2 on") else: From baddde62339a6a3e3349e96d212f9d6dd31d02a0 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 27 Aug 2026 00:59:34 -0600 Subject: [PATCH 36/39] Add a note on how ndep for cplhist is in units that don't need to be converted, but the code assumes because they are only divided into 2 fields that they are and wrongly divideds by a 1000 --- datm/cime_config/stream_definition_datm.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index fef04c14f..80c3a8f89 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -5307,6 +5307,8 @@ $DATM_CPLHIST_DIR/$DATM_CPLHIST_CASE.cpl.hx.atm.24h.avrg.%ymd-00000.nc + ^ + atmImp_Faxa_ndep1 Faxa_ndep_nhx atmImp_Faxa_ndep2 Faxa_ndep_noy From 93d3b156122ac3f294f846609f38771ea5dbbbee Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 27 Aug 2026 11:59:25 -0600 Subject: [PATCH 37/39] Add a comment about the clim_1850_cesm3_for_cmip7 option to DATM_PRESNDEP --- datm/cime_config/config_component.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index b9b387d5a..1331c643b 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -104,6 +104,8 @@ char + + none,clim_1850_cesm3_for_cmip7,clim_1850_cmip7,clim_2000_cmip7,clim_2010_cmip7,hist_cmip7,clim_1850_cmip6,clim_2000_cmip6,clim_2010_cmip6,hist_cmip6,SSP1-2.6,SSP2-4.5,SSP3-7.0,SSP5-3.4,SSP5-8.5,cplhist clim_2000 From 1b961f0fb25ec9fcab64800df61d5da55853d30f Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 29 Aug 2026 01:41:57 -0600 Subject: [PATCH 38/39] Remove accidental character that screwed up the XML syntax, and adjust the comment for clarity on that same line --- datm/cime_config/stream_definition_datm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/cime_config/stream_definition_datm.xml b/datm/cime_config/stream_definition_datm.xml index 80c3a8f89..9c11ef540 100644 --- a/datm/cime_config/stream_definition_datm.xml +++ b/datm/cime_config/stream_definition_datm.xml @@ -5307,7 +5307,7 @@ $DATM_CPLHIST_DIR/$DATM_CPLHIST_CASE.cpl.hx.atm.24h.avrg.%ymd-00000.nc - ^ + atmImp_Faxa_ndep1 Faxa_ndep_nhx atmImp_Faxa_ndep2 Faxa_ndep_noy From 4a6f49ceb275512dac3adaa5176e957c1c4cad42 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Sat, 29 Aug 2026 02:07:48 -0600 Subject: [PATCH 39/39] Add coupling_mode as an attribute for the cesm settings that could conflict with noresm, set DATM_CPLHIST_DIR to UNSET as requested by @mvertens and @billsacks, but add to the description about how to set it using \$DATM_CPLHIST_CASE and gives and example path to use in your archive directory for a previous case you ran, remove setting of year align to 1 for CESM CPLHIST, and remove dependency on CLM version and make it just _CLM for these CPLHIST settings we are only supporting modern CPLHIST files, so if you did CPLHIST with running CLM50 you`d want it to work the same in those cases as well --- datm/cime_config/config_component.xml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/datm/cime_config/config_component.xml b/datm/cime_config/config_component.xml index 1331c643b..41305fe2a 100644 --- a/datm/cime_config/config_component.xml +++ b/datm/cime_config/config_component.xml @@ -110,7 +110,7 @@ clim_2000 clim_1850_cmip6 - clim_1850_cesm3_for_cmip7 + clim_1850_cesm3_for_cmip7 clim_2000_cmip6 clim_2010_cmip6 hist_cmip6 @@ -181,7 +181,7 @@ cmip6_20tr omip.iaf omip.jra - cplhist + cplhist run_component_datm env_run.xml @@ -211,13 +211,22 @@ char - $CIME_OUTPUT_ROOT/archive/$DATM_CPLHIST_CASE/cpl/hist + UNSET - $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm + $DIN_LOC_ROOT/cplhist/cesm3_0/$DATM_CPLHIST_CASE/atm run_component_datm env_run.xml - directory for coupler history data mode (only used for when DATM_MODE is CPLHIST) + + Directory for coupler history data mode (used when DATM_MODE is CPLHIST) + May also be used if and of these are set to cplhist: DATM_PRESAERO, DATM_NDEP, DATM_CO2_TSERIES, DATM_PRESO3, or DATM_TOPO + NOTE: This needs to be the full directory path where the CPLHIST files are stored, including the subdirectory for the CASENAME (that can be set using $DATM_CPLHIST_CASE) + We thus recommend that $DATM_CPLHIST_CASE be used in here to specify that case subdirectory. + This allows the DATM_CPLHIST_DIR to be set for all your CPLHIST datafiles, and you only need to modify $DATM_CPLHIST_CASE to point to a different CASE. + For example, to use the CPLHIST data generated from a case that you ran do this: + ./xmlchange DATM_CPLHIST_DIR='$CIME_OUTPUT_ROOT/archive/$DATM_CPLHIST_CASE/cpl/hist' + Which will then use the CPL history files in your archive directory where the case that created the CPLHIST data you want to use is" + @@ -225,7 +234,7 @@ UNSET - b.e30_alpha08o.B1850C_MTso.ne30_t232_wgx3.330 + b.e30_alpha08o.B1850C_MTso.ne30_t232_wgx3.330 run_component_datm env_run.xml @@ -242,7 +251,6 @@ 1 1 1 - 1 1895 1901 1901 @@ -292,7 +300,7 @@ 1901 1901 0 - 101 + 101 2000 1972 1948 @@ -364,7 +372,7 @@ 1920 1920 -1 - 101 + 101 2004 2004 1972