From 4f3232a760ca6b6c02fd65c7fe6801b6a1cd2f90 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 25 Aug 2016 11:46:46 -0600 Subject: [PATCH 01/19] add option allow_baseline_overwrite to generate_baseline, fix issue 310 --- scripts/Tools/component_generate_baseline | 13 ++++++++++--- utils/python/CIME/case_run.py | 16 ++-------------- utils/python/CIME/hist_utils.py | 9 ++++++++- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/scripts/Tools/component_generate_baseline b/scripts/Tools/component_generate_baseline index 8fbc4bd2a255..79ec82278978 100755 --- a/scripts/Tools/component_generate_baseline +++ b/scripts/Tools/component_generate_baseline @@ -35,18 +35,25 @@ OR parser.add_argument("-b", "--baseline-dir", help="Use custom baseline dir") + parser.add_argument("-o", "--allow-baseline-overwrite", action="store_true", + help="In the CESM workflow existing baseline directories are not" + " overwritten by default, this flag allows overwrite") + + args = parser.parse_args(args[1:]) CIME.utils.handle_standard_logging_options(args) - return args.caseroot, args.baseline_dir + return args.caseroot, args.baseline_dir, args.allow_baseline_overwrite ############################################################################### def _main_func(description): ############################################################################### - caseroot, baseline_dir = parse_command_line(sys.argv, description) + caseroot, baseline_dir, allow_baseline_overwrite = \ + parse_command_line(sys.argv, description) with Case(caseroot) as case: - success, comments = generate_baseline(case, baseline_dir) + success, comments = generate_baseline(case, baseline_dir, + allow_baseline_overwrite) print comments sys.exit(0 if success else 1) diff --git a/utils/python/CIME/case_run.py b/utils/python/CIME/case_run.py index eb3c0df001a9..5471408f7dcf 100644 --- a/utils/python/CIME/case_run.py +++ b/utils/python/CIME/case_run.py @@ -2,7 +2,6 @@ from CIME.XML.standard_module_setup import * from CIME.case_submit import submit from CIME.XML.files import Files -from CIME.XML.component import Component from CIME.XML.machines import Machines from CIME.utils import append_status, touch, gzip_existing_file from CIME.check_lockedfiles import check_lockedfiles @@ -329,19 +328,8 @@ def save_logs(case, lid): caseroot = case.get_value("CASEROOT") rundir = case.get_value("RUNDIR") - - # get components - files = Files() - config_file = files.get_value("CONFIG_DRV_FILE") - component = Component(config_file) - comps = [x.lower() for x in component.get_valid_model_components()] - comps = [x.replace('drv', 'cpl') for x in comps] - model = [case.get_value("MODEL")] - comps = comps + model - - # for each component, compress log files and copy to logdir - for comp in comps: - logfile = os.path.join(rundir, comp + '.log.' + lid) + logfiles = glob.glob(os.path.join(rundir,"*.log.%s"%(lid))) + for logfile in logfiles: if os.path.isfile(logfile): logfile_gz = gzip_existing_file(logfile) shutil.copy(logfile_gz, diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 395af87fa952..7cf3ed07ea11 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -249,12 +249,14 @@ def get_extension(model, filepath): expect(m is not None, "Failed to get extension for file '%s'" % filepath) return m.groups()[0] -def generate_baseline(case, baseline_dir=None): +def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): """ copy the current test output to baseline result case - The case containing the hist files to be copied into baselines baseline_dir - Optionally, specify a specific baseline dir, otherwise it will be computed from case config + allow_baseline_overwrite is only used in the CESM model workflow and must be true + to generate baselines to an existing directory. returns (SUCCESS, comments) """ @@ -269,6 +271,11 @@ def generate_baseline(case, baseline_dir=None): if not os.path.isdir(basegen_dir): os.makedirs(basegen_dir) + if (os.path.isdir(os.path.join(basegen_dir,testcase)) and + case.get_value("MODEL") == "CESM" and not allow_baseline_overwrite): + expect(False, " Cowardly refusing to overwrite existing baseline directory") + + comments = "Generating baselines into '%s'\n" % basegen_dir num_gen = 0 for model in _iter_model_file_substrs(case): From 32eecbab07a07f3c98019fc10597c7b04daa4669 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 25 Aug 2016 20:30:47 -0600 Subject: [PATCH 02/19] support for multiinstance cases --- utils/python/CIME/hist_utils.py | 58 +++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 7cf3ed07ea11..2a36e9a51d7c 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -41,21 +41,7 @@ def _get_latest_hist_files(testcase, model, from_dir, suffix=""): date_match = re.compile(r"(\d\d\d\d)-(\d\d)-(\d\d)-(\d\d\d\d\d).nc") for hist in test_hists: ext = get_extension(model, hist) - if ext in latest_files: - s1 = date_match.search(hist) - if s1 is None: - latest_files[ext] = hist - continue - (yr,month,day,time) = s1.group(1,2,3,4) - s2 = date_match.search(latest_files[ext]) - (pyr,pmonth,pday,ptime) = s2.group(1,2,3,4) - if yr > pyr or (yr == pyr and month > pmonth) or \ - (yr == pyr and month == pmonth and day > pday) or \ - (yr == pyr and month == pmonth and day == pday and time > ptime): - latest_files[ext] = hist - logger.debug("ext %s hist %s %s"%(ext,hist,latest_files)) - else: - latest_files[ext] = hist + latest_files[ext] = hist for key in latest_files.keys(): histlist.append(latest_files[key]) @@ -105,15 +91,25 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): >>> hists2 = ['cpl.h2.nc.SUF2', 'cpl.h3.nc.SUF2', 'cpl.h4.nc.SUF2'] >>> _hists_match('cpl', hists1, hists2, 'SUF1', 'SUF2') (['FOO.G.cpl.h1.nc.SUF1'], ['cpl.h4.nc.SUF2'], [('FOO.G.cpl.h2.nc.SUF1', 'cpl.h2.nc.SUF2'), ('FOO.G.cpl.h3.nc.SUF1', 'cpl.h3.nc.SUF2')]) + >>> hists1 = ['cam.h0.1850-01-08-00000.nc'] + >>> hists2 = ['cam_0001.h0.1850-01-08-00000.nc'] + >>> _hists_match('cam', hists1, hists2, '', '') + ([], [], [('cam.h0.1850-01-08-00000.nc', 'cam_0001.h0.1850-01-08-00000.nc')]) """ normalized1, normalized2 = [], [] + multiinst = False for hists, suffix, normalized in [(hists1, suffix1, normalized1), (hists2, suffix2, normalized2)]: for hist in hists: normalized_name = hist[hist.rfind(model):] if suffix1 != "": - expect(normalized_name.endswith(suffix), "How did '%s' hot have suffix '%s'" % (hist, suffix)) + expect(normalized_name.endswith(suffix), "How did '%s' not have suffix '%s'" % (hist, suffix)) normalized_name = normalized_name[:len(normalized_name) - len(suffix)] + m = re.search("(.*%s.*)_(\d\d\d\d)(.h.*)"%model, normalized_name) + if m is not None: + multiinst = True + normalized_name = m.group(1)+m.group(3) + normalized.append(normalized_name) set_of_1_not_2 = set(normalized1) - set(normalized2) @@ -124,8 +120,9 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): both = set(normalized1) & set(normalized2) match_ups = sorted([ (hists1[normalized1.index(item)], hists2[normalized2.index(item)]) for item in both]) - expect(len(match_ups) + len(set_of_1_not_2) == len(hists1), "Programming error1") - expect(len(match_ups) + len(set_of_2_not_1) == len(hists2), "Programming error2") + if not multiinst: + expect(len(match_ups) + len(set_of_1_not_2) == len(hists1), "Programming error1") + expect(len(match_ups) + len(set_of_2_not_1) == len(hists2), "Programming error2") return one_not_two, two_not_one, match_ups @@ -242,12 +239,20 @@ def get_extension(model, filepath): 'hi' >>> get_extension("cpl", "TESTRUNDIFF_Mmpi-serial.f19_g16_rx1.A.melvin_gnu.C.fake_testing_only_20160816_164150-20160816_164240.cpl.h.nc") 'h' + >>> get_extension("clm","clm2_0002.h0.1850-01-06-00000.nc") + '0002.h0' """ basename = os.path.basename(filepath) - ext_regex = re.compile(r'.*%s.*[.](h.?)([.][^.]+)?[.]nc' % model) + ext_regex = re.compile(r'.*%s[^_]*_?(\d{4})?[.](h.?)([.][^.]+)?[.]nc' % model) + m = ext_regex.match(basename) expect(m is not None, "Failed to get extension for file '%s'" % filepath) - return m.groups()[0] + if m.group(1) is not None: + result = m.group(1)+'.'+m.group(2) + else: + result = m.group(2) + + return result def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): """ @@ -288,7 +293,18 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): baseline = os.path.join(basegen_dir, basename) if os.path.exists(baseline): os.remove(baseline) - + ''' + special care for multi-instance cases, only keep first instance and + remove instance string from filename + ''' + m = re.search("(.*%s.*)_(\d\d\d\d)(.h.*)"%model, baseline) + if m is not None: + inst = m.group(2) + if inst != '0001': + continue + baseline = m.group(1)+m.group(3) + + logger.debug("Found multiinstance hist file %s"%hist) shutil.copy(hist, baseline) comments += " generating baseline '%s' from file %s\n" % (baseline, hist) From d14f787ec15ed4085bc7a0c8147db4d7a208bee0 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 25 Aug 2016 22:23:32 -0600 Subject: [PATCH 03/19] fix issues with create_test and scripts_regression_test --- utils/python/CIME/case_run.py | 1 - utils/python/CIME/hist_utils.py | 18 ++++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/utils/python/CIME/case_run.py b/utils/python/CIME/case_run.py index 5471408f7dcf..89d4bfd3ca20 100644 --- a/utils/python/CIME/case_run.py +++ b/utils/python/CIME/case_run.py @@ -1,7 +1,6 @@ from CIME.XML.standard_module_setup import * from CIME.case_submit import submit -from CIME.XML.files import Files from CIME.XML.machines import Machines from CIME.utils import append_status, touch, gzip_existing_file from CIME.check_lockedfiles import check_lockedfiles diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 2a36e9a51d7c..ccb305535447 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -38,7 +38,6 @@ def _get_latest_hist_files(testcase, model, from_dir, suffix=""): test_hists = _get_all_hist_files(testcase, model, from_dir, suffix) latest_files = {} histlist = [] - date_match = re.compile(r"(\d\d\d\d)-(\d\d)-(\d\d)-(\d\d\d\d\d).nc") for hist in test_hists: ext = get_extension(model, hist) latest_files[ext] = hist @@ -105,10 +104,10 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): expect(normalized_name.endswith(suffix), "How did '%s' not have suffix '%s'" % (hist, suffix)) normalized_name = normalized_name[:len(normalized_name) - len(suffix)] - m = re.search("(.*%s.*)_(\d\d\d\d)(.h.*)"%model, normalized_name) + m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) if m is not None: multiinst = True - normalized_name = m.group(1)+m.group(3) + normalized_name = m.group(1)+m.group(2) normalized.append(normalized_name) @@ -293,14 +292,13 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): baseline = os.path.join(basegen_dir, basename) if os.path.exists(baseline): os.remove(baseline) - ''' - special care for multi-instance cases, only keep first instance and - remove instance string from filename - ''' - m = re.search("(.*%s.*)_(\d\d\d\d)(.h.*)"%model, baseline) + + #special care for multi-instance cases, + #only keep first instance and + #remove instance string from filename + m = re.search("(.*%s.*)_([0-9]{4})(.h.*)"%model, baseline) if m is not None: - inst = m.group(2) - if inst != '0001': + if m.group(2) != '0001': continue baseline = m.group(1)+m.group(3) From f8d9bdb567e24fc80e4dc7c235e9d474053ad074 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 26 Aug 2016 10:47:51 -0600 Subject: [PATCH 04/19] add special case for cpl compare in multiinst cases --- utils/python/CIME/hist_utils.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index ccb305535447..56960e9c8775 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -91,7 +91,7 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): >>> _hists_match('cpl', hists1, hists2, 'SUF1', 'SUF2') (['FOO.G.cpl.h1.nc.SUF1'], ['cpl.h4.nc.SUF2'], [('FOO.G.cpl.h2.nc.SUF1', 'cpl.h2.nc.SUF2'), ('FOO.G.cpl.h3.nc.SUF1', 'cpl.h3.nc.SUF2')]) >>> hists1 = ['cam.h0.1850-01-08-00000.nc'] - >>> hists2 = ['cam_0001.h0.1850-01-08-00000.nc'] + >>> hists2 = ['cam_0001.h0.1850-01-08-00000.nc','cam_0002.h0.1850-01-08-00000.nc'] >>> _hists_match('cam', hists1, hists2, '', '') ([], [], [('cam.h0.1850-01-08-00000.nc', 'cam_0001.h0.1850-01-08-00000.nc')]) """ @@ -134,8 +134,10 @@ def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): num_compared = 0 comments = "Comparing hists for case '%s' dir1='%s', suffix1='%s', dir2='%s' suffix2='%s'\n" % \ (testcase, from_dir1, suffix1, from_dir2, suffix2) - + multiinst_cpl_compare = False for model in _iter_model_file_substrs(case): + if model == 'cpl' and suffix2 == 'multiinst': + multiinst_cpl_compare = True comments += " comparing model '%s'\n" % model hists1 = _get_latest_hist_files(testcase, model, from_dir1, suffix1) hists2 = _get_latest_hist_files(testcase, model, from_dir2, suffix2) @@ -154,7 +156,7 @@ def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): num_compared += len(match_ups) for hist1, hist2 in match_ups: - success, cprnc_comments = cprnc(hist1, hist2, case, from_dir1) + success, cprnc_comments = cprnc(hist1, hist2, case, from_dir1, multiinst_cpl_compare) if success: comments += " %s matched %s\n" % (hist1, hist2) else: @@ -180,7 +182,7 @@ def compare_test(case, suffix1, suffix2): return _compare_hists(case, rundir, rundir, suffix1, suffix2) -def cprnc(file1, file2, case, rundir): +def cprnc(file1, file2, case, rundir, multiinst_cpl_compare=False): """ Run cprnc to compare two individual nc files @@ -194,7 +196,14 @@ def cprnc(file1, file2, case, rundir): cprnc_exe = case.get_value("CCSM_CPRNC") basename = os.path.basename(file1) stat, out, _ = run_cmd("%s -m %s %s 2>&1 | tee %s/%s.cprnc.out" % (cprnc_exe, file1, file2, rundir, basename)) - return (stat == 0 and "files seem to be IDENTICAL" in out, out) + if multiinst_cpl_compare: + # In a multiinstance test the cpl hist file will have a different number of + # dimensions and so cprnc will indicate that the files seem to be DIFFERENT + # in this case we only want to check that the fields we are able to compare + # have no differences. + return (stat == 0 and " 0 had non-zero differences" in out, out) + else: + return (stat == 0 and "files seem to be IDENTICAL" in out, out) def compare_baseline(case, baseline_dir=None): """ From 1e8b10fe1aefa1e1c0ffeb65c1576bd925e3dc08 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 26 Aug 2016 11:40:47 -0600 Subject: [PATCH 05/19] skip this test in cesm --- utils/python/tests/scripts_regression_tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/python/tests/scripts_regression_tests.py b/utils/python/tests/scripts_regression_tests.py index a10342641ee6..379ad4274cab 100755 --- a/utils/python/tests/scripts_regression_tests.py +++ b/utils/python/tests/scripts_regression_tests.py @@ -664,6 +664,8 @@ class P_TestJenkinsGenericJob(TestCreateTestCommon): ########################################################################### def setUp(self): ########################################################################### + if CIME.utils.get_model() != "acme": + self.skipTest("Skipping Jenkins tests. ACME feature") TestCreateTestCommon.setUp(self) # Need to run in a subdir in order to not have CTest clash. Name it From ec5430f8d227cb9c859b95c88844dcdb1c76c747 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 26 Aug 2016 14:04:09 -0600 Subject: [PATCH 06/19] make help message consistant with create_test --- scripts/Tools/component_generate_baseline | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Tools/component_generate_baseline b/scripts/Tools/component_generate_baseline index 79ec82278978..1d154b5bbf9a 100755 --- a/scripts/Tools/component_generate_baseline +++ b/scripts/Tools/component_generate_baseline @@ -36,9 +36,9 @@ OR help="Use custom baseline dir") parser.add_argument("-o", "--allow-baseline-overwrite", action="store_true", - help="In the CESM workflow existing baseline directories are not" - " overwritten by default, this flag allows overwrite") - + help="If the generate baseline option is specified with a baseline directory option " + "existing tests in that directory will not be overwritten unless this flag is provided." + "You can use bless-test-results to bless baselines from a recent run.") args = parser.parse_args(args[1:]) From 76a7dbcf1fc8496e652ea0a45810127470a3530b Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 26 Aug 2016 14:22:59 -0600 Subject: [PATCH 07/19] make help message consistant with create_test --- scripts/Tools/component_generate_baseline | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Tools/component_generate_baseline b/scripts/Tools/component_generate_baseline index 1d154b5bbf9a..0dcca7681c8b 100755 --- a/scripts/Tools/component_generate_baseline +++ b/scripts/Tools/component_generate_baseline @@ -36,9 +36,9 @@ OR help="Use custom baseline dir") parser.add_argument("-o", "--allow-baseline-overwrite", action="store_true", - help="If the generate baseline option is specified with a baseline directory option " - "existing tests in that directory will not be overwritten unless this flag is provided." - "You can use bless-test-results to bless baselines from a recent run.") + help="By default an attempt to overwrite an existing baseline directory " + "will raise an error. Specifying this option allows " + "existing baseline directories to be silently overwritten.") args = parser.parse_args(args[1:]) From cf2de416d096d5a0a3cef97b5c98541122a7a7ec Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 26 Aug 2016 16:30:03 -0600 Subject: [PATCH 08/19] need to copy CaseDocs to baseline dir --- utils/python/CIME/hist_utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 56960e9c8775..b68bc8c4bd41 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -288,7 +288,6 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): case.get_value("MODEL") == "CESM" and not allow_baseline_overwrite): expect(False, " Cowardly refusing to overwrite existing baseline directory") - comments = "Generating baselines into '%s'\n" % basegen_dir num_gen = 0 for model in _iter_model_file_substrs(case): @@ -315,6 +314,10 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): shutil.copy(hist, baseline) comments += " generating baseline '%s' from file %s\n" % (baseline, hist) + # Copy namelist files from CaseDocs + shutil.copytree(os.path.join(case.get_value("CASEROOT"),"CaseDocs"), + os.path.join(basegen_dir,"CaseDocs")) + expect(num_gen > 0, "Could not generate any hist files for case '%s', something is seriously wrong" % testcase) return True, comments From 3922258fe4153423858fe0923c541457876120c4 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 29 Aug 2016 10:20:36 -0600 Subject: [PATCH 09/19] response to review comments --- scripts/create_test | 2 +- utils/python/CIME/hist_utils.py | 58 +++++++++++++++---- utils/python/CIME/test_scheduler.py | 10 ++-- utils/python/CIME/utils.py | 9 ++- utils/python/jenkins_generic_job.py | 2 +- .../python/tests/scripts_regression_tests.py | 39 +++++++------ 6 files changed, 79 insertions(+), 41 deletions(-) diff --git a/scripts/create_test b/scripts/create_test index 39a71856e8af..fa5044d24f4f 100755 --- a/scripts/create_test +++ b/scripts/create_test @@ -257,7 +257,7 @@ OR args.no_batch = True if args.test_id is None: - args.test_id = CIME.utils.get_utc_timestamp() + args.test_id = CIME.utils.get_timestamp() if args.testfile is not None: with open(args.testfile, "r") as fd: diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index b68bc8c4bd41..4c8753063e03 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -93,21 +93,27 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): >>> hists1 = ['cam.h0.1850-01-08-00000.nc'] >>> hists2 = ['cam_0001.h0.1850-01-08-00000.nc','cam_0002.h0.1850-01-08-00000.nc'] >>> _hists_match('cam', hists1, hists2, '', '') - ([], [], [('cam.h0.1850-01-08-00000.nc', 'cam_0001.h0.1850-01-08-00000.nc')]) + ([], [], [('cam.h0.1850-01-08-00000.nc', 'cam_0001.h0.1850-01-08-00000.nc'), ('cam.h0.1850-01-08-00000.nc', 'cam_0002.h0.1850-01-08-00000.nc')]) + >>> hists1 = ['cam_0001.h0.1850-01-08-00000.nc.base','cam_0002.h0.1850-01-08-00000.nc.base'] + >>> hists2 = ['cam_0001.h0.1850-01-08-00000.nc.rest','cam_0002.h0.1850-01-08-00000.nc.rest'] + >>> _hists_match('cam', hists1, hists2, 'base', 'rest') + ([], [], [('cam_0001.h0.1850-01-08-00000.nc.base', 'cam_0001.h0.1850-01-08-00000.nc.rest'), ('cam_0002.h0.1850-01-08-00000.nc.base', 'cam_0002.h0.1850-01-08-00000.nc.rest')]) """ normalized1, normalized2 = [], [] + multi_normalized1, multi_normalized2 = [], [] multiinst = False - for hists, suffix, normalized in [(hists1, suffix1, normalized1), (hists2, suffix2, normalized2)]: + + for hists, suffix, normalized, multi_normalized in [(hists1, suffix1, normalized1, multi_normalized1), (hists2, suffix2, normalized2, multi_normalized2)]: for hist in hists: normalized_name = hist[hist.rfind(model):] - if suffix1 != "": + if suffix != "": expect(normalized_name.endswith(suffix), "How did '%s' not have suffix '%s'" % (hist, suffix)) normalized_name = normalized_name[:len(normalized_name) - len(suffix)] m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) if m is not None: multiinst = True - normalized_name = m.group(1)+m.group(2) + multi_normalized.append(m.group(1)+m.group(2)) normalized.append(normalized_name) @@ -118,8 +124,31 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): two_not_one = sorted([hists2[normalized2.index(item)] for item in set_of_2_not_1]) both = set(normalized1) & set(normalized2) + match_ups = sorted([ (hists1[normalized1.index(item)], hists2[normalized2.index(item)]) for item in both]) - if not multiinst: + if multiinst: + new_two_not_one = [] + new_one_not_two = [] + for normalized_name in two_not_one: + m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) + if m is not None: + multi_normalized = m.group(1)+m.group(2) + if multi_normalized in one_not_two: + match_ups.append((multi_normalized, normalized_name) ) + else: + new_two_not_one.append(normalized_name) + two_not_one = new_two_not_one + for normalized_name in one_not_two: + m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) + if m is not None: + multi_normalized = m.group(1)+m.group(2) + if multi_normalized in two_not_one: + match_ups.append((multi_normalized, normalized_name) ) + else: + new_one_not_two.append(normalized_name) + one_not_two = new_one_not_two + + else: expect(len(match_ups) + len(set_of_1_not_2) == len(hists1), "Programming error1") expect(len(match_ups) + len(set_of_2_not_1) == len(hists2), "Programming error2") @@ -155,6 +184,7 @@ def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): all_success = False num_compared += len(match_ups) + for hist1, hist2 in match_ups: success, cprnc_comments = cprnc(hist1, hist2, case, from_dir1, multiinst_cpl_compare) if success: @@ -251,7 +281,7 @@ def get_extension(model, filepath): '0002.h0' """ basename = os.path.basename(filepath) - ext_regex = re.compile(r'.*%s[^_]*_?(\d{4})?[.](h.?)([.][^.]+)?[.]nc' % model) + ext_regex = re.compile(r'.*%s[^_]*_?([0-9]{4})?[.](h.?)([.][^.]+)?[.]nc' % model) m = ext_regex.match(basename) expect(m is not None, "Failed to get extension for file '%s'" % filepath) @@ -268,8 +298,7 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): case - The case containing the hist files to be copied into baselines baseline_dir - Optionally, specify a specific baseline dir, otherwise it will be computed from case config - allow_baseline_overwrite is only used in the CESM model workflow and must be true - to generate baselines to an existing directory. + allow_baseline_overwrite must be true to generate baselines to an existing directory. returns (SUCCESS, comments) """ @@ -285,7 +314,7 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): os.makedirs(basegen_dir) if (os.path.isdir(os.path.join(basegen_dir,testcase)) and - case.get_value("MODEL") == "CESM" and not allow_baseline_overwrite): + not allow_baseline_overwrite): expect(False, " Cowardly refusing to overwrite existing baseline directory") comments = "Generating baselines into '%s'\n" % basegen_dir @@ -315,8 +344,15 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): comments += " generating baseline '%s' from file %s\n" % (baseline, hist) # Copy namelist files from CaseDocs - shutil.copytree(os.path.join(case.get_value("CASEROOT"),"CaseDocs"), - os.path.join(basegen_dir,"CaseDocs")) + base_case_docs = os.path.join(basegen_dir,"CaseDocs") + caseroot = case.get_value("CASEROOT") + if os.path.isdir(base_case_docs): + files = os.listdir(os.path.join(caseroot,"CaseDocs")) + for f in files: + shutil.copy2(os.path.join(caseroot, "CaseDocs", f), base_case_docs) + else: + shutil.copytree(os.path.join(case.get_value("CASEROOT"),"CaseDocs"), + os.path.join(basegen_dir,"CaseDocs")) expect(num_gen > 0, "Could not generate any hist files for case '%s', something is seriously wrong" % testcase) diff --git a/utils/python/CIME/test_scheduler.py b/utils/python/CIME/test_scheduler.py index ca75cd852f14..a40a7cda70c4 100644 --- a/utils/python/CIME/test_scheduler.py +++ b/utils/python/CIME/test_scheduler.py @@ -46,7 +46,7 @@ def __init__(self, test_names, test_data=None, ########################################################################### self._cime_root = CIME.utils.get_cime_root() self._cime_model = CIME.utils.get_model() - + self._allow_baseline_overwrite = allow_baseline_overwrite self._save_timing = save_timing self._queue = queue self._test_data = {} if test_data is None else test_data # Format: {test_name -> {data_name -> data}} @@ -80,7 +80,7 @@ def __init__(self, test_names, test_data=None, self._test_root = self._test_root.replace("$PROJECT", self._project) self._test_root = os.path.abspath(self._test_root) - self._test_id = test_id if test_id is not None else CIME.utils.get_utc_timestamp() + self._test_id = test_id if test_id is not None else CIME.utils.get_timestamp() self._compiler = self._machobj.get_default_compiler() if compiler is None else compiler @@ -114,11 +114,8 @@ def __init__(self, test_names, test_data=None, "Missing baseline comparison directory %s" % full_baseline_dir) # the following is to assure that the existing generate directory is not overwritten - if self._baseline_gen_name and not allow_baseline_overwrite: + if self._baseline_gen_name: full_baseline_dir = os.path.join(self._baseline_root, self._baseline_gen_name) - expect(not os.path.isdir(full_baseline_dir), - "Refusing to overwrite existing baseline directory, use -o to force overwrite %s" % full_baseline_dir) - else: self._baseline_root = None @@ -368,6 +365,7 @@ def _xml_phase(self, test): if self._baseline_gen_name: test_argv += " -generate %s" % self._baseline_gen_name basegen_case_fullpath = os.path.join(self._baseline_root,self._baseline_gen_name, test) + expect(self._allow_baseline_overwrite or not os.path.isdir(basegen_case_fullpath), "Baseline directory already exists") logger.warn("basegen_case is %s"%basegen_case_fullpath) envtest.set_value("BASELINE_NAME_GEN", self._baseline_gen_name) envtest.set_value("BASEGEN_CASE", os.path.join(self._baseline_gen_name, test)) diff --git a/utils/python/CIME/utils.py b/utils/python/CIME/utils.py index fbf7a675eb1f..09d054b1d259 100644 --- a/utils/python/CIME/utils.py +++ b/utils/python/CIME/utils.py @@ -489,14 +489,17 @@ def find_proc_id(proc_name=None, return list(rv) -def get_utc_timestamp(timestamp_format="%Y%m%d_%H%M%S"): +def get_timestamp(timestamp_format="%Y%m%d_%H%M%S", utc_time=False): """ Get a string representing the current UTC time in format: YYMMDD_HHMMSS The format can be changed if needed. """ - utc_time_tuple = time.gmtime() - return time.strftime(timestamp_format, utc_time_tuple) + if utc_time: + time_tuple = time.gmtime() + else: + time_tuple = time.localtime() + return time.strftime(timestamp_format, time_tuple) def get_project(machobj=None): """ diff --git a/utils/python/jenkins_generic_job.py b/utils/python/jenkins_generic_job.py index 8f595c1f823d..6fe3fcf6d4aa 100644 --- a/utils/python/jenkins_generic_job.py +++ b/utils/python/jenkins_generic_job.py @@ -107,7 +107,7 @@ def jenkins_generic_job(generate_baselines, submit_to_cdash, no_batch, batch_args = "--no-batch" if no_batch else "" pjob_arg = "" if parallel_jobs is None else "-j %d" % parallel_jobs - test_id = "%s_%s" % (test_id_root, CIME.utils.get_utc_timestamp()) + test_id = "%s_%s" % (test_id_root, CIME.utils.get_timestamp()) create_test_cmd = "./create_test %s --test-root %s -t %s %s %s %s" % \ (test_suite, test_root, test_id, baseline_args, batch_args, pjob_arg) diff --git a/utils/python/tests/scripts_regression_tests.py b/utils/python/tests/scripts_regression_tests.py index 379ad4274cab..0708cde0ca9f 100755 --- a/utils/python/tests/scripts_regression_tests.py +++ b/utils/python/tests/scripts_regression_tests.py @@ -169,7 +169,7 @@ def setUp(self): self._do_teardown = [] def test_createnewcase(self): - testdir = os.path.join(self._testroot, 'scripts_regression_tests.testcreatenewcase.%s'% CIME.utils.get_utc_timestamp()) + testdir = os.path.join(self._testroot, 'scripts_regression_tests.testcreatenewcase.%s'% CIME.utils.get_timestamp()) if os.path.exists(testdir): shutil.rmtree(testdir) @@ -182,7 +182,7 @@ def test_createnewcase(self): self._do_teardown.append(testdir) def test_user_mods(self): - testdir = os.path.join(self._testroot, 'scripts_regression_tests.testusermods.%s'% CIME.utils.get_utc_timestamp()) + testdir = os.path.join(self._testroot, 'scripts_regression_tests.testusermods.%s'% CIME.utils.get_timestamp()) if os.path.exists(testdir): shutil.rmtree(testdir) @@ -218,10 +218,10 @@ class M_TestWaitForTests(unittest.TestCase): def setUp(self): ########################################################################### self._testroot = MACHINE.get_value("CESMSCRATCHROOT") - self._testdir_all_pass = os.path.join(self._testroot, 'scripts_regression_tests.testdir_all_pass.%s'% CIME.utils.get_utc_timestamp()) - self._testdir_with_fail = os.path.join(self._testroot, 'scripts_regression_tests.testdir_with_fail.%s'% CIME.utils.get_utc_timestamp()) - self._testdir_unfinished = os.path.join(self._testroot, 'scripts_regression_tests.testdir_unfinished.%s'% CIME.utils.get_utc_timestamp()) - self._testdir_unfinished2 = os.path.join(self._testroot, 'scripts_regression_tests.testdir_unfinished2.%s'% CIME.utils.get_utc_timestamp()) + self._testdir_all_pass = os.path.join(self._testroot, 'scripts_regression_tests.testdir_all_pass.%s'% CIME.utils.get_timestamp()) + self._testdir_with_fail = os.path.join(self._testroot, 'scripts_regression_tests.testdir_with_fail.%s'% CIME.utils.get_timestamp()) + self._testdir_unfinished = os.path.join(self._testroot, 'scripts_regression_tests.testdir_unfinished.%s'% CIME.utils.get_timestamp()) + self._testdir_unfinished2 = os.path.join(self._testroot, 'scripts_regression_tests.testdir_unfinished2.%s'% CIME.utils.get_timestamp()) testdirs = [self._testdir_all_pass, self._testdir_with_fail, self._testdir_unfinished, self._testdir_unfinished2] for testdir in testdirs: if os.path.exists(testdir): @@ -422,7 +422,7 @@ def setUp(self): ########################################################################### self._thread_error = None self._unset_proxy = setup_proxy() - self._baseline_name = "fake_testing_only_%s" % CIME.utils.get_utc_timestamp() + self._baseline_name = "fake_testing_only_%s" % CIME.utils.get_timestamp() self._machine = MACHINE.get_machine_name() self._baseline_area = MACHINE.get_value("CCSM_BASELINE") self._testroot = MACHINE.get_value("CESMSCRATCHROOT") @@ -483,10 +483,10 @@ def test_create_test_rebless_namelist(self): else: genarg = "-g %s -o"%self._baseline_name comparg = "-c %s"%self._baseline_name - self.simple_test(True, "%s -n -t %s-%s" % (genarg,self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -n -t %s-%s" % (genarg,self._baseline_name, CIME.utils.get_timestamp())) # Basic namelist compare - self.simple_test(True, "%s -n -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -n -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_timestamp())) # Modify namelist fake_nl = """ @@ -508,13 +508,13 @@ def test_create_test_rebless_namelist(self): nl_file.write(fake_nl) # Basic namelist compare should now fail - self.simple_test(False, "%s -n -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(False, "%s -n -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_timestamp())) # Regen - self.simple_test(True, "%s -n -t %s-%s" % (genarg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -n -t %s-%s" % (genarg, self._baseline_name, CIME.utils.get_timestamp())) # Basic namelist compare should now pass again - self.simple_test(True, "%s -n -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -n -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_timestamp())) ############################################################################### class O_TestTestScheduler(TestCreateTestCommon): @@ -600,7 +600,7 @@ def test_a_phases(self): def test_b_full(self): ########################################################################### tests = update_acme_tests.get_full_test_names(["cime_test_only"], self._machine, self._compiler) - test_id="%s-%s" % (self._baseline_name, CIME.utils.get_utc_timestamp()) + test_id="%s-%s" % (self._baseline_name, CIME.utils.get_timestamp()) ct = TestScheduler(tests, test_id=test_id, no_batch=NO_BATCH) build_fail_test = [item for item in tests if "TESTBUILDFAIL." in item][0] @@ -728,7 +728,7 @@ def test_jenkins_generic_job(self): self.simple_test(True, "-t cime_test_only_pass -g -b %s" % self._baseline_name) self.assert_num_leftovers() - build_name = "jenkins_generic_job_pass_%s" % CIME.utils.get_utc_timestamp() + build_name = "jenkins_generic_job_pass_%s" % CIME.utils.get_timestamp() self.simple_test(True, "-t cime_test_only_pass -b %s" % self._baseline_name, build_name=build_name) self.assert_num_leftovers() # jenkins_generic_job should have automatically cleaned up leftovers from prior run assert_dashboard_has_build(self, build_name) @@ -736,7 +736,7 @@ def test_jenkins_generic_job(self): ########################################################################### def test_jenkins_generic_job_kill(self): ########################################################################### - build_name = "jenkins_generic_job_kill_%s" % CIME.utils.get_utc_timestamp() + build_name = "jenkins_generic_job_kill_%s" % CIME.utils.get_timestamp() run_thread = threading.Thread(target=self.threaded_test, args=(False, " -t cime_test_only_slow_pass -b master --baseline-compare=no", build_name)) run_thread.daemon = True run_thread.start() @@ -790,16 +790,16 @@ def test_bless_test_results(self): genarg = "-g %s -o"%self._baseline_name comparg = "-c %s"%self._baseline_name - self.simple_test(True, "%s -t %s-%s" % (genarg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -t %s-%s" % (genarg, self._baseline_name, CIME.utils.get_timestamp())) # Hist compare should pass - self.simple_test(True, "%s -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_timestamp())) # Change behavior os.environ["TESTRUNDIFF_ALTERNATE"] = "True" # Hist compare should now fail - test_id = "%s-%s" % (self._baseline_name, CIME.utils.get_utc_timestamp()) + test_id = "%s-%s" % (self._baseline_name, CIME.utils.get_timestamp()) self.simple_test(False, "%s -t %s" % (comparg, test_id)) # compare_test_results should detect the fail @@ -816,7 +816,7 @@ def test_bless_test_results(self): run_cmd_no_fail("%s/bless_test_results --hist-only --force -b %s -t %s" % (TOOLS_DIR, self._baseline_name, test_id)) # Hist compare should now pass again - self.simple_test(True, "%s -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_utc_timestamp())) + self.simple_test(True, "%s -t %s-%s" % (comparg, self._baseline_name, CIME.utils.get_timestamp())) ############################################################################### @unittest.skip("Disabling this test until we figure out how to integrate ACME tests and CIME xml files.") @@ -1007,6 +1007,7 @@ def setUp(self): self._do_teardown = [] testdir = os.path.join(self._testroot, 'scripts_regression_tests.testscripts.%s'% CIME.utils.get_utc_timestamp()) + if os.path.exists(testdir): shutil.rmtree(testdir) From f0f757141f1e9b155952030530a7d0cb89a6d34c Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 29 Aug 2016 13:39:17 -0600 Subject: [PATCH 10/19] change debug log message --- utils/python/CIME/test_scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/python/CIME/test_scheduler.py b/utils/python/CIME/test_scheduler.py index a40a7cda70c4..da9e8cb5d0cc 100644 --- a/utils/python/CIME/test_scheduler.py +++ b/utils/python/CIME/test_scheduler.py @@ -366,7 +366,7 @@ def _xml_phase(self, test): test_argv += " -generate %s" % self._baseline_gen_name basegen_case_fullpath = os.path.join(self._baseline_root,self._baseline_gen_name, test) expect(self._allow_baseline_overwrite or not os.path.isdir(basegen_case_fullpath), "Baseline directory already exists") - logger.warn("basegen_case is %s"%basegen_case_fullpath) + logger.debug("basegen_case is %s"%basegen_case_fullpath) envtest.set_value("BASELINE_NAME_GEN", self._baseline_gen_name) envtest.set_value("BASEGEN_CASE", os.path.join(self._baseline_gen_name, test)) if self._baseline_cmp_name: From 01b58880a82294b0fc03f0aa087898e3ed216922 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sat, 27 Aug 2016 06:56:59 -0600 Subject: [PATCH 11/19] Rewrite NCK test using SystemTestsCompareTwo It seems the NCK test wasn't working right before; hopefully this will fix it Test suite: None Test baseline: N/A Test namelist changes: N/A Test status: N/A Fixes: None User interface changes?: No Code review: None --- cime_config/config_tests.xml | 4 + utils/python/CIME/SystemTests/nck.py | 156 +++++++-------------------- 2 files changed, 45 insertions(+), 115 deletions(-) diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index 5c86ade09e51..e6dd7ef601ca 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -393,6 +393,10 @@ LII CLM initial condition interpolation test 1 -1 FALSE + FALSE + none + $STOP_OPTION + $STOP_N diff --git a/utils/python/CIME/SystemTests/nck.py b/utils/python/CIME/SystemTests/nck.py index 09902cde3f7c..78b13c8256c0 100644 --- a/utils/python/CIME/SystemTests/nck.py +++ b/utils/python/CIME/SystemTests/nck.py @@ -1,126 +1,52 @@ """ -Implementation of the CIME NCK test. This class inherits from SystemTestsCommon +Implementation of the CIME NCK test: Tests multi-instance + +This does two runs: In the first, we use one instance per component; in the +second, we use two instances per components. NTASKS are changed in each run so +that the number of tasks per instance is the same for both runs. -Build two exectuables for this test, the first is a default build the -second halves the number of tasks and runs two instances for each component Lay all of the components out sequentially """ -import shutil + from CIME.XML.standard_module_setup import * +from CIME.SystemTests.system_tests_compare_two import SystemTestsCompareTwo from CIME.case_setup import case_setup -import CIME.utils -from CIME.SystemTests.system_tests_common import SystemTestsCommon logger = logging.getLogger(__name__) -class NCK(SystemTestsCommon): - - def __init__(self, case): - """ - initialize a test object - """ - SystemTestsCommon.__init__(self, case) - - def build_phase(self, sharedlib_only=False, model_only=False): - ''' - build can be called once (sharedlib_only and model_only both False) - or twice (once with each true) - This test requires a sharedlib build for both phases - we must handle both cases correctly - ''' - exeroot = self._case.get_value("EXEROOT") - cime_model = CIME.utils.get_model() - if not model_only: - machpes1 = os.path.join("LockedFiles","env_mach_pes.orig.xml") - if os.path.isfile(machpes1): - shutil.copy(machpes1,"env_mach_pes.xml") - else: - shutil.copy("env_mach_pes.xml", machpes1) - - # Build two exectuables for this test, the first is a default build, the - # second halves the number of tasks and runs two instances for each component - # Lay all of the components out sequentially - for bld in range(1,3): - logging.warn("Starting bld %s"%bld) - machpes = os.path.join("LockedFiles","env_mach_pes.NCK%s.xml"%bld) - if model_only: - # This file should have been created in the sharedlib_only phase - shutil.copy(machpes,"env_mach_pes.xml") - self._case.read_xml() - else: - for comp in ['ATM','OCN','WAV','GLC','ICE','ROF','LND']: - self._case.set_value("NINST_%s"%comp, bld) - ntasks = self._case.get_value("NTASKS_%s"%comp) - if(bld == 1): - if ( ntasks > 1 ): - self._case.set_value("NTASKS_%s"%comp, int(ntasks/2)) - else: - self._case.set_value("NTASKS_%s"%comp, ntasks*2) - self._case.flush() - - case_setup(self._case, test_mode=True, reset=True) - if not sharedlib_only: - self.clean_build() - - self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only) - if not model_only: - shutil.copy("env_mach_pes.xml", machpes) - if not sharedlib_only: - shutil.move("%s/%s.exe"%(exeroot,cime_model),"%s/%s.exe.NCK%s"%(exeroot,cime_model,bld)) - shutil.copy("env_build.xml",os.path.join("LockedFiles","env_build.NCK%s.xml"%bld)) - - # Because mira/cetus interprets its run script differently than - # other systems we need to copy the original env_mach_pes.xml back -# shutil.copy(machpes1,"env_mach_pes.xml") -# shutil.copy("env_mach_pes.xml", -# os.path.join("LockedFiles","env_mach_pes.xml")) +class NCK(SystemTestsCompareTwo): - def run_phase(self): - os.chdir(self._caseroot) + _COMPONENT_LIST = ('ATM','OCN','WAV','GLC','ICE','ROF','LND') - exeroot = self._case.get_value("EXEROOT") - cime_model = CIME.utils.get_model() - - # Reset beginning test settings - expect(os.path.exists("LockedFiles/env_mach_pes.NCK1.xml"), - "ERROR: LockedFiles/env_mach_pes.NCK1.xml does not exist\n" - " this would been produced in the build - must run case.test_build") - - shutil.copy("LockedFiles/env_mach_pes.NCK1.xml", "env_mach_pes.xml") - shutil.copy("env_mach_pes.xml", "LockedFiles/env_mach_pes.xml") - shutil.copy("%s/%s.exe.NCK1" % (exeroot, cime_model), - "%s/%s.exe" % (exeroot, cime_model)) - shutil.copy("LockedFiles/env_build.NCK1.xml", "env_build.xml") - shutil.copy("env_build.xml", "LockedFiles/env_build.xml") - - stop_n = self._case.get_value("STOP_N") - stop_option = self._case.get_value("STOP_OPTION") - - self._case.set_value("HIST_N", stop_n) - self._case.set_value("HIST_OPTION", stop_option) - self._case.set_value("CONTINUE_RUN", False) - self._case.set_value("REST_OPTION", "none") - self._case.flush() - - #====================================================================== - # do an initial run test with NINST 1 - #====================================================================== - logger.info("default: doing a %s %s with NINST1" % (stop_n, stop_option)) - self.run_indv() - - #====================================================================== - # do an initial run test with NINST 2 - # want to run on same pe counts per instance and same cpl pe count - #====================================================================== - - os.remove("%s/%s.exe" % (exeroot, cime_model)) - shutil.copy("%s/%s.exe.NCK2" % (exeroot, cime_model), - "%s/%s.exe" % (exeroot, cime_model)) - shutil.copy("LockedFiles/env_build.NCK2.xml", "env_build.xml") - shutil.copy("env_build.xml", "LockedFiles/env_build.xml") - shutil.copy("LockedFiles/env_mach_pes.NCK2.xml", "env_mach_pes.xml") - shutil.copy("env_mach_pes.xml", "LockedFiles/env_mach_pes.xml") - - logger.info("default: doing a %s %s with NINST2" % (stop_n, stop_option)) - self.run_indv(suffix="multiinst") - self._component_compare_test("base", "multiinst") + def __init__(self, case): + SystemTestsCompareTwo.__init__(self, case, + separate_builds = True, + run_two_suffix = 'multiinst', + run_one_description = 'one instance', + run_two_description = 'two instances') + + def _common_setup(self): + # We start by halving the number of tasks for both cases. This ensures + # that we use the same number of tasks per instance in both cases: For + # the two-instance case, we'll double this halved number, so you may + # think that the halving was unnecessary; but it's needed in case the + # original NTASKS was odd. (e.g., for NTASKS originally 15, we want to + # use NTASKS = int(15/2) * 2 = 14 tasks for case two.) + for comp in _COMPONENT_LIST: + ntasks = self._case.get_value("NTASKS_%s"%comp) + if ( ntasks > 1 ): + self._case.set_value("NTASKS_%s"%comp, int(ntasks/2)) + + def _case_one_setup(self): + for comp in _COMPONENT_LIST: + self._case.set_value("NINST_%s"%comp, 1) + + case_setup(self._case, test_mode=True, reset=True) + + def _case_two_setup(self): + for comp in _COMPONENT_LIST: + self._case.set_value("NINST_%s"%comp, 2) + ntasks = self._case.get_value("NTASKS_%s"%comp) + self._case.set_value("NTASKS_%s"%comp, ntasks*2) + + case_setup(self._case, test_mode=True, reset=True) From d9c0e98063d9f2366881a4a7828a5c9c08e2d31e Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sat, 27 Aug 2016 07:08:05 -0600 Subject: [PATCH 12/19] Fix minor bug Test suite: None Test baseline: N/A Test namelist changes: N/A Test status: N/A Fixes: None User interface changes?: No Code review: None --- utils/python/CIME/SystemTests/nck.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/python/CIME/SystemTests/nck.py b/utils/python/CIME/SystemTests/nck.py index 78b13c8256c0..0e35d2e2f53a 100644 --- a/utils/python/CIME/SystemTests/nck.py +++ b/utils/python/CIME/SystemTests/nck.py @@ -32,19 +32,19 @@ def _common_setup(self): # think that the halving was unnecessary; but it's needed in case the # original NTASKS was odd. (e.g., for NTASKS originally 15, we want to # use NTASKS = int(15/2) * 2 = 14 tasks for case two.) - for comp in _COMPONENT_LIST: + for comp in self._COMPONENT_LIST: ntasks = self._case.get_value("NTASKS_%s"%comp) if ( ntasks > 1 ): self._case.set_value("NTASKS_%s"%comp, int(ntasks/2)) def _case_one_setup(self): - for comp in _COMPONENT_LIST: + for comp in self._COMPONENT_LIST: self._case.set_value("NINST_%s"%comp, 1) case_setup(self._case, test_mode=True, reset=True) def _case_two_setup(self): - for comp in _COMPONENT_LIST: + for comp in self._COMPONENT_LIST: self._case.set_value("NINST_%s"%comp, 2) ntasks = self._case.get_value("NTASKS_%s"%comp) self._case.set_value("NTASKS_%s"%comp, ntasks*2) From b354e170f469333e791d973ec458805ed890a1df Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 30 Aug 2016 08:31:29 -0600 Subject: [PATCH 13/19] fix issue with user_mods/test_mods --- driver_cpl/cime_config/config_component.xml | 12 +++++++++- utils/python/CIME/case.py | 25 +++++++++++---------- utils/python/CIME/case_setup.py | 6 ++++- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/driver_cpl/cime_config/config_component.xml b/driver_cpl/cime_config/config_component.xml index 7abe633670c0..8fbdb8959bb8 100644 --- a/driver_cpl/cime_config/config_component.xml +++ b/driver_cpl/cime_config/config_component.xml @@ -2956,12 +2956,22 @@ char - /UNSET + UNSET test env_test.xml standard full pathname of the cprnc executable + + char + UNSET + user_mods + env_case.xml + path to user mods under TESTS_MODS_DIR or USER_MODS_DIR + + + + diff --git a/utils/python/CIME/case.py b/utils/python/CIME/case.py index cedf850bdde7..e56d642c3fe7 100644 --- a/utils/python/CIME/case.py +++ b/utils/python/CIME/case.py @@ -321,29 +321,29 @@ def _set_compset_and_pesfile(self, compset_name, user_compset=False, pesfile=Non # Determine the compsets file for this component compsets_filename = files.get_value("COMPSETS_SPEC_FILE", {"component":component}) - pes_filename = files.get_value("PES_SPEC_FILE" , {"component":component}) - tests_filename = files.get_value("TESTS_SPEC_FILE" , {"component":component}, resolved=False) - tests_mods_dir = files.get_value("TESTS_MODS_DIR" , {"component":component}, resolved=False) - user_mods_dir = files.get_value("USER_MODS_DIR" , {"component":component}, resolved=False) # If the file exists, read it and see if there is a match for the compset alias or longname if (os.path.isfile(compsets_filename)): compsets = Compsets(compsets_filename) match = compsets.get_compset_match(name=compset_name) + pesfile = files.get_value("PES_SPEC_FILE" , {"component":component}) if match is not None: - self._pesfile = pes_filename + self._pesfile = pesfile self._compsetsfile = compsets_filename self._compsetname = match - self.set_value("COMPSETS_SPEC_FILE" , + tests_filename = files.get_value("TESTS_SPEC_FILE" , {"component":component}, resolved=False) + tests_mods_dir = files.get_value("TESTS_MODS_DIR" , {"component":component}, resolved=False) + user_mods_dir = files.get_value("USER_MODS_DIR" , {"component":component}, resolved=False) + self.set_lookup_value("COMPSETS_SPEC_FILE" , files.get_value("COMPSETS_SPEC_FILE", {"component":component}, resolved=False)) - self.set_value("TESTS_SPEC_FILE" , tests_filename) - self.set_value("TESTS_MODS_DIR" , tests_mods_dir) - self.set_value("USER_MODS_DIR" , user_mods_dir) - self.set_value("PES_SPEC_FILE" , + self.set_lookup_value("TESTS_SPEC_FILE" , tests_filename) + self.set_lookup_value("TESTS_MODS_DIR" , tests_mods_dir) + self.set_lookup_value("USER_MODS_DIR" , user_mods_dir) + self.set_lookup_value("PES_SPEC_FILE" , files.get_value("PES_SPEC_FILE" , {"component":component}, resolved=False)) logger.info("Compset longname is %s " %(match)) logger.info("Compset specification file is %s" %(compsets_filename)) - logger.info("Pes specification file is %s" %(pes_filename)) + logger.info("Pes specification file is %s" %(pesfile)) return if user_compset is True: @@ -351,7 +351,7 @@ def _set_compset_and_pesfile(self, compset_name, user_compset=False, pesfile=Non logger.warn("Could not find a compset match for either alias or longname in %s" %(compset_name)) self._compsetname = compset_name self._pesfile = pesfile - self.set_value("PES_SPEC_FILE", pesfile) + self.set_lookup_value("PES_SPEC_FILE", pesfile) else: expect(False, "Could not find a compset match for either alias or longname in %s" %(compset_name)) @@ -821,6 +821,7 @@ def apply_user_mods(self, user_mods_dir=None): else: user_mods_path = self.get_value('USER_MODS_DIR') user_mods_path = os.path.join(user_mods_path, user_mods_dir) + self.set_value("USER_MODS_FULLPATH",user_mods_path) ninst_vals = {} for i in xrange(1,len(self._component_classes)): comp_class = self._component_classes[i] diff --git a/utils/python/CIME/case_setup.py b/utils/python/CIME/case_setup.py index 4713e70c6061..fed306c2a2d7 100644 --- a/utils/python/CIME/case_setup.py +++ b/utils/python/CIME/case_setup.py @@ -258,12 +258,16 @@ def _case_setup_impl(case, caseroot, casebaseid, clean=False, test_mode=False, r _build_usernl_files(case, "drv", "cpl") - if case.get_value("TEST"): + user_mods_path = case.get_value("USER_MODS_USE_CASE") + if user_mods_path is not None: + apply_user_mods(caseroot, user_mods_path=user_mods_path, ninst=ninst) + elif case.get_value("TEST"): test_mods = parse_test_name(casebaseid)[6] if test_mods is not None: user_mods_path = os.path.join(case.get_value("TESTS_MODS_DIR"), test_mods) apply_user_mods(caseroot, user_mods_path=user_mods_path, ninst=ninst) + # Run preview namelists for scripts logger.info("preview_namelists") preview_namelists(case) From 3bbd2225df1e3346e608dd318cb715157a23217c Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 30 Aug 2016 08:35:39 -0600 Subject: [PATCH 14/19] add a documentation note to hist_utils.py --- utils/python/CIME/hist_utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 4c8753063e03..920475348656 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -126,6 +126,10 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): both = set(normalized1) & set(normalized2) match_ups = sorted([ (hists1[normalized1.index(item)], hists2[normalized2.index(item)]) for item in both]) + + # In some multiinstance cases hist1 will be single instance and hist2 multiinstance + # or visa-versa if this is the case match all instances in one with the single instance + # in the other and remove the files from the unmatched list. if multiinst: new_two_not_one = [] new_one_not_two = [] From 3539f8c3d5d922afc5ad25e8cb1a41bdb66789d6 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 30 Aug 2016 16:32:48 -0600 Subject: [PATCH 15/19] rework and clean up _hists_match --- scripts/create_newcase | 2 +- utils/python/CIME/SystemTests/nck.py | 11 ++- .../CIME/SystemTests/system_tests_common.py | 9 -- utils/python/CIME/XML/pes.py | 2 +- utils/python/CIME/hist_utils.py | 93 +++++++++---------- utils/python/CIME/test_scheduler.py | 9 +- 6 files changed, 62 insertions(+), 64 deletions(-) diff --git a/scripts/create_newcase b/scripts/create_newcase index bba9d90de5d8..1ec1921248a0 100755 --- a/scripts/create_newcase +++ b/scripts/create_newcase @@ -33,7 +33,7 @@ def parse_command_line(args, cimeroot): "To see list of current compsets, use the utility manage_case in this directory") parser.add_argument("--mach", "-mach", - help="(required) Specify a machine. " + help="Specify a machine. " "To see list of current machines, use the utility manage_case in this directory") parser.add_argument("--compiler", "-compiler", diff --git a/utils/python/CIME/SystemTests/nck.py b/utils/python/CIME/SystemTests/nck.py index 0e35d2e2f53a..d00edea7b8d8 100644 --- a/utils/python/CIME/SystemTests/nck.py +++ b/utils/python/CIME/SystemTests/nck.py @@ -16,9 +16,8 @@ class NCK(SystemTestsCompareTwo): - _COMPONENT_LIST = ('ATM','OCN','WAV','GLC','ICE','ROF','LND') - def __init__(self, case): + self._comp_classes = [] SystemTestsCompareTwo.__init__(self, case, separate_builds = True, run_two_suffix = 'multiinst', @@ -32,19 +31,21 @@ def _common_setup(self): # think that the halving was unnecessary; but it's needed in case the # original NTASKS was odd. (e.g., for NTASKS originally 15, we want to # use NTASKS = int(15/2) * 2 = 14 tasks for case two.) - for comp in self._COMPONENT_LIST: + self._comp_classes = self._case.get_value("COMP_CLASSES").split(',') + self._comp_classes.remove("DRV") + for comp in self._comp_classes: ntasks = self._case.get_value("NTASKS_%s"%comp) if ( ntasks > 1 ): self._case.set_value("NTASKS_%s"%comp, int(ntasks/2)) def _case_one_setup(self): - for comp in self._COMPONENT_LIST: + for comp in self._comp_classes: self._case.set_value("NINST_%s"%comp, 1) case_setup(self._case, test_mode=True, reset=True) def _case_two_setup(self): - for comp in self._COMPONENT_LIST: + for comp in self._comp_classes: self._case.set_value("NINST_%s"%comp, 2) ntasks = self._case.get_value("NTASKS_%s"%comp) self._case.set_value("NTASKS_%s"%comp, ntasks*2) diff --git a/utils/python/CIME/SystemTests/system_tests_common.py b/utils/python/CIME/SystemTests/system_tests_common.py index d101daeb220b..136c47b0c2e6 100644 --- a/utils/python/CIME/SystemTests/system_tests_common.py +++ b/utils/python/CIME/SystemTests/system_tests_common.py @@ -152,9 +152,6 @@ def run(self): logger.warning(excmsg) append_status(excmsg, sfile="TestStatus.log") - # Always try to report, should NOT throw an exception - self.report() - # Writing the run status should be the very last thing due to wait_for_tests time_taken = time.time() - start_time status = TEST_PASS_STATUS if success else TEST_FAIL_STATUS @@ -225,12 +222,6 @@ def _coupler_log_indicates_run_complete(self): logger.info("%s is not compressed, assuming run failed"%newestcpllogfile) return False - def report(self): - """ - Please explain what kind of things happen in report - """ - pass - def _component_compare_move(self, suffix): comments = move(self._case, suffix) append_status(comments, sfile="TestStatus.log") diff --git a/utils/python/CIME/XML/pes.py b/utils/python/CIME/XML/pes.py index 0efb853cfffe..01ea3e940cf8 100644 --- a/utils/python/CIME/XML/pes.py +++ b/utils/python/CIME/XML/pes.py @@ -67,7 +67,7 @@ def find_pes_layout(self, grid, compset, machine, pesize_opts='M'): pes_ntasks, pes_nthrds, pes_rootpe, other_settings = {}, {}, {}, {} for node in pe_select: vid = node.tag - logger.warn("vid is %s"%vid) + logger.debug("vid is %s"%vid) if "ntasks" in vid: for child in node: pes_ntasks[child.tag.upper()] = child.text diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 920475348656..2ce1aa1e969c 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -25,11 +25,12 @@ def _get_all_hist_files(testcase, model, from_dir, suffix=""): test_hists.extend(glob.glob("%s/%s.%s*.h.*.nc%s" % (from_dir, testcase, model, suffix))) # suffix == "" implies baseline comparison, baseline hist files have simpler names + if suffix == "": - test_hists.extend(glob.glob("%s/%s.h.nc" % (from_dir, model))) - test_hists.extend(glob.glob("%s/%s.h?.nc" % (from_dir, model))) - test_hists.extend(glob.glob("%s/%s.h.*.nc" % (from_dir, model))) - test_hists.extend(glob.glob("%s/%s.h?.*.nc" % (from_dir, model))) + test_hists.extend(glob.glob("%s/%s*.h.nc" % (from_dir, model))) + test_hists.extend(glob.glob("%s/%s*.h?.nc" % (from_dir, model))) + test_hists.extend(glob.glob("%s/%s*.h.*.nc" % (from_dir, model))) + test_hists.extend(glob.glob("%s/%s*.h?.*.nc" % (from_dir, model))) test_hists.sort() return test_hists @@ -78,6 +79,7 @@ def move(case, suffix): return comments + def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): """ return (num in set 1 but not 2 , num in set 2 but not 1, matchups) @@ -110,7 +112,7 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): expect(normalized_name.endswith(suffix), "How did '%s' not have suffix '%s'" % (hist, suffix)) normalized_name = normalized_name[:len(normalized_name) - len(suffix)] - m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) + m = re.search("(.+)_[0-9]{4}(.+.nc)",normalized_name) if m is not None: multiinst = True multi_normalized.append(m.group(1)+m.group(2)) @@ -127,35 +129,30 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): match_ups = sorted([ (hists1[normalized1.index(item)], hists2[normalized2.index(item)]) for item in both]) - # In some multiinstance cases hist1 will be single instance and hist2 multiinstance - # or visa-versa if this is the case match all instances in one with the single instance - # in the other and remove the files from the unmatched list. - if multiinst: - new_two_not_one = [] - new_one_not_two = [] - for normalized_name in two_not_one: - m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) - if m is not None: - multi_normalized = m.group(1)+m.group(2) - if multi_normalized in one_not_two: - match_ups.append((multi_normalized, normalized_name) ) - else: - new_two_not_one.append(normalized_name) - two_not_one = new_two_not_one - for normalized_name in one_not_two: - m = re.search(r"(.*%s.*)_[0-9]{4}(.h.*)"%model, normalized_name) - if m is not None: - multi_normalized = m.group(1)+m.group(2) - if multi_normalized in two_not_one: - match_ups.append((multi_normalized, normalized_name) ) - else: - new_one_not_two.append(normalized_name) - one_not_two = new_one_not_two - - else: + if multi_normalized1 != multi_normalized2: + if set(multi_normalized1) == set(normalized2): + for idx, norm_hist1 in enumerate(multi_normalized1): + for idx1, hist2 in enumerate(hists2): + norm_hist2 = normalized2[idx1] + if norm_hist1 == norm_hist2: + match_ups.append((hists1[idx], hist2)) + if hist2 in two_not_one: + two_not_one.remove(hist2) + if hists1[idx] in one_not_two: + one_not_two.remove(hists1[idx]) + if set(multi_normalized2) == set(normalized1): + for idx, norm_hist2 in enumerate(multi_normalized2): + for idx1, hist1 in enumerate(hists1): + norm_hist1 = normalized1[idx1] + if norm_hist2 == norm_hist1: + match_ups.append((hist1, hists2[idx])) + if hist1 in one_not_two: + one_not_two.remove(hist1) + if hists2[idx] in two_not_one: + two_not_one.remove(hists2[idx]) + if not multiinst: expect(len(match_ups) + len(set_of_1_not_2) == len(hists1), "Programming error1") expect(len(match_ups) + len(set_of_2_not_1) == len(hists2), "Programming error2") - return one_not_two, two_not_one, match_ups def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): @@ -174,7 +171,6 @@ def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): comments += " comparing model '%s'\n" % model hists1 = _get_latest_hist_files(testcase, model, from_dir1, suffix1) hists2 = _get_latest_hist_files(testcase, model, from_dir2, suffix2) - if len(hists1) == 0 and len(hists2) == 0: comments += " no hist files found for model %s\n" % model continue @@ -190,7 +186,7 @@ def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): num_compared += len(match_ups) for hist1, hist2 in match_ups: - success, cprnc_comments = cprnc(hist1, hist2, case, from_dir1, multiinst_cpl_compare) + success, cprnc_comments = cprnc(model, hist1, hist2, case, from_dir1, multiinst_cpl_compare) if success: comments += " %s matched %s\n" % (hist1, hist2) else: @@ -216,7 +212,7 @@ def compare_test(case, suffix1, suffix2): return _compare_hists(case, rundir, rundir, suffix1, suffix2) -def cprnc(file1, file2, case, rundir, multiinst_cpl_compare=False): +def cprnc(model, file1, file2, case, rundir, multiinst_cpl_compare=False): """ Run cprnc to compare two individual nc files @@ -229,7 +225,21 @@ def cprnc(file1, file2, case, rundir, multiinst_cpl_compare=False): """ cprnc_exe = case.get_value("CCSM_CPRNC") basename = os.path.basename(file1) - stat, out, _ = run_cmd("%s -m %s %s 2>&1 | tee %s/%s.cprnc.out" % (cprnc_exe, file1, file2, rundir, basename)) + multiinst_regex = re.compile(r'.*%s[^_]*(_[0-9]{4})[.]h.?[.][^.]+?[.]nc' % model) + mstr = '' + mstr1 = '' + mstr2 = '' + # If one is a multiinstance file but the other is not add an instance string + m1 = multiinst_regex.match(file1) + m2 = multiinst_regex.match(file2) + if m1 is not None: + mstr1 = m1.group(1) + if m2 is not None: + mstr2 = m2.group(1) + if mstr1 != mstr2: + mstr = mstr1+mstr2 + + stat, out, _ = run_cmd("%s -m %s %s 2>&1 | tee %s/%s%s.cprnc.out" % (cprnc_exe, file1, file2, rundir, basename, mstr)) if multiinst_cpl_compare: # In a multiinstance test the cpl hist file will have a different number of # dimensions and so cprnc will indicate that the files seem to be DIFFERENT @@ -347,17 +357,6 @@ def generate_baseline(case, baseline_dir=None, allow_baseline_overwrite=False): shutil.copy(hist, baseline) comments += " generating baseline '%s' from file %s\n" % (baseline, hist) - # Copy namelist files from CaseDocs - base_case_docs = os.path.join(basegen_dir,"CaseDocs") - caseroot = case.get_value("CASEROOT") - if os.path.isdir(base_case_docs): - files = os.listdir(os.path.join(caseroot,"CaseDocs")) - for f in files: - shutil.copy2(os.path.join(caseroot, "CaseDocs", f), base_case_docs) - else: - shutil.copytree(os.path.join(case.get_value("CASEROOT"),"CaseDocs"), - os.path.join(basegen_dir,"CaseDocs")) - expect(num_gen > 0, "Could not generate any hist files for case '%s', something is seriously wrong" % testcase) return True, comments diff --git a/utils/python/CIME/test_scheduler.py b/utils/python/CIME/test_scheduler.py index da9e8cb5d0cc..9bb336eb999e 100644 --- a/utils/python/CIME/test_scheduler.py +++ b/utils/python/CIME/test_scheduler.py @@ -116,6 +116,14 @@ def __init__(self, test_names, test_data=None, # the following is to assure that the existing generate directory is not overwritten if self._baseline_gen_name: full_baseline_dir = os.path.join(self._baseline_root, self._baseline_gen_name) + existing_baselines = [] + for test_name in test_names: + test_baseline = os.path.join(full_baseline_dir, test_name) + if os.path.isdir(test_baseline): + existing_baselines.append(test_baseline) + expect(allow_baseline_overwrite or len(existing_baselines) == 0, + "Baseline directories already exists %s\n"\ + "Use --allow_baseline_overwrite to avoid this error"%existing_baselines) else: self._baseline_root = None @@ -365,7 +373,6 @@ def _xml_phase(self, test): if self._baseline_gen_name: test_argv += " -generate %s" % self._baseline_gen_name basegen_case_fullpath = os.path.join(self._baseline_root,self._baseline_gen_name, test) - expect(self._allow_baseline_overwrite or not os.path.isdir(basegen_case_fullpath), "Baseline directory already exists") logger.debug("basegen_case is %s"%basegen_case_fullpath) envtest.set_value("BASELINE_NAME_GEN", self._baseline_gen_name) envtest.set_value("BASEGEN_CASE", os.path.join(self._baseline_gen_name, test)) From 02dc89bbb0934486cdbd8d6248090a35fb6e7013 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 30 Aug 2016 16:52:51 -0600 Subject: [PATCH 16/19] git rid of the dot --- utils/python/CIME/hist_utils.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 2ce1aa1e969c..363f92f58365 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -110,7 +110,7 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): normalized_name = hist[hist.rfind(model):] if suffix != "": expect(normalized_name.endswith(suffix), "How did '%s' not have suffix '%s'" % (hist, suffix)) - normalized_name = normalized_name[:len(normalized_name) - len(suffix)] + normalized_name = normalized_name[:len(normalized_name) - len(suffix) - 1] m = re.search("(.+)_[0-9]{4}(.+.nc)",normalized_name) if m is not None: @@ -129,7 +129,10 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): match_ups = sorted([ (hists1[normalized1.index(item)], hists2[normalized2.index(item)]) for item in both]) + # Special case - comparing multiinstance to single instance files + if multi_normalized1 != multi_normalized2: + # in this case hists1 contains multiinstance hists2 does not if set(multi_normalized1) == set(normalized2): for idx, norm_hist1 in enumerate(multi_normalized1): for idx1, hist2 in enumerate(hists2): @@ -140,6 +143,9 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): two_not_one.remove(hist2) if hists1[idx] in one_not_two: one_not_two.remove(hists1[idx]) + # in this case hists2 contains multiinstance hists1 does not + print multi_normalized2 + print normalized1 if set(multi_normalized2) == set(normalized1): for idx, norm_hist2 in enumerate(multi_normalized2): for idx1, hist1 in enumerate(hists1): @@ -150,9 +156,11 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): one_not_two.remove(hist1) if hists2[idx] in two_not_one: two_not_one.remove(hists2[idx]) + if not multiinst: expect(len(match_ups) + len(set_of_1_not_2) == len(hists1), "Programming error1") expect(len(match_ups) + len(set_of_2_not_1) == len(hists2), "Programming error2") + return one_not_two, two_not_one, match_ups def _compare_hists(case, from_dir1, from_dir2, suffix1="", suffix2=""): From 3e30771e3ab8f864d5b6386454e614f5fc22323a Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 30 Aug 2016 18:36:02 -0600 Subject: [PATCH 17/19] remove debug print statements --- utils/python/CIME/hist_utils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 363f92f58365..9870f8e2fed9 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -144,8 +144,6 @@ def _hists_match(model, hists1, hists2, suffix1="", suffix2=""): if hists1[idx] in one_not_two: one_not_two.remove(hists1[idx]) # in this case hists2 contains multiinstance hists1 does not - print multi_normalized2 - print normalized1 if set(multi_normalized2) == set(normalized1): for idx, norm_hist2 in enumerate(multi_normalized2): for idx1, hist1 in enumerate(hists1): From 8224cb487d07a236c2eac3fe306f8a546341cf13 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Wed, 31 Aug 2016 07:57:42 -0600 Subject: [PATCH 18/19] fix pylint issues --- utils/python/CIME/hist_utils.py | 2 +- utils/python/tests/scripts_regression_tests.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/python/CIME/hist_utils.py b/utils/python/CIME/hist_utils.py index 9870f8e2fed9..31258c33eb1e 100644 --- a/utils/python/CIME/hist_utils.py +++ b/utils/python/CIME/hist_utils.py @@ -239,7 +239,7 @@ def cprnc(model, file1, file2, case, rundir, multiinst_cpl_compare=False): m1 = multiinst_regex.match(file1) m2 = multiinst_regex.match(file2) if m1 is not None: - mstr1 = m1.group(1) + mstr1 = m1.group(1) if m2 is not None: mstr2 = m2.group(1) if mstr1 != mstr2: diff --git a/utils/python/tests/scripts_regression_tests.py b/utils/python/tests/scripts_regression_tests.py index 0708cde0ca9f..dd4f5e3d280f 100755 --- a/utils/python/tests/scripts_regression_tests.py +++ b/utils/python/tests/scripts_regression_tests.py @@ -1006,7 +1006,7 @@ def setUp(self): self._testdirs = [] self._do_teardown = [] - testdir = os.path.join(self._testroot, 'scripts_regression_tests.testscripts.%s'% CIME.utils.get_utc_timestamp()) + testdir = os.path.join(self._testroot, 'scripts_regression_tests.testscripts.%s'% CIME.utils.get_timestamp()) if os.path.exists(testdir): shutil.rmtree(testdir) From ea7c23aa20ce95ead716e3170d5116a994ef2a64 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Wed, 31 Aug 2016 09:06:31 -0600 Subject: [PATCH 19/19] make sure these test always build threaded --- cime_config/config_tests.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index e6dd7ef601ca..43d7519c428f 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -169,6 +169,7 @@ LII CLM initial condition interpolation test 22 0 FALSE + TRUE @@ -179,6 +180,7 @@ LII CLM initial condition interpolation test ndays 11 FALSE + TRUE