Repository: ESMCI/cime

Issue:
case_st_archive.py:_get_datenames needs to use MULTI_DRIVER
@gold2718 @jedwards4b
This issue stems from #2240.
CESM+DART cases will generally be built with the MULTI_DRIVER option,
since it saves a lot of core hours and wall clock.
_get_datenames creates a list of all of the cpl restart files in order to know
how many restart file sets need to be archived.  But  in the M_D cases
there are NINST cpl restart files for each date stamp: cpl_0001.r, ..., 
so the archiver tries to archive NINST*#_dates file sets.
The proposed fix is to pass "case" down to _get_datenames,
query MULTI_DRIVER, and assemble the appropriate list
of restart sets.  I've coded and tested this, and will issue a PR soon,
unless I shouldn't.


Discussion:

Resolving patch:
diff --git a/scripts/lib/CIME/case_setup.py b/scripts/lib/CIME/case_setup.py
--- a/scripts/lib/CIME/case_setup.py
+++ b/scripts/lib/CIME/case_setup.py
@@ -37,7 +37,7 @@ def _build_usernl_files(case, model, comp):
     multi_driver = case.get_value("MULTI_DRIVER")
     if multi_driver:
         ninst_max = case.get_value("NINST_MAX")
-        if model not in ("DRV","CPL"):
+        if model not in ("DRV","CPL","ESP"):
             ninst_model = case.get_value("NINST_{}".format(model))
             expect(ninst_model==ninst_max,"MULTI_DRIVER mode, all components must have same NINST value.  NINST_{} != {}".format(model,ninst_max))
     if comp == "cpl":
diff --git a/scripts/lib/CIME/case_st_archive.py b/scripts/lib/CIME/case_st_archive.py
--- a/scripts/lib/CIME/case_st_archive.py
+++ b/scripts/lib/CIME/case_st_archive.py
@@ -21,17 +21,32 @@ def _get_archive_file_fn(copy_only):
     return shutil.copyfile if copy_only else shutil.move
 
 ###############################################################################
-def _get_datenames(rundir, casename):
+def _get_datenames(case):
 ###############################################################################
     """
     Returns the datetime objects specifying the times of each file
     Note we are assuming that the coupler restart files exist and are consistent with other component datenames
     Not doc-testable due to filesystem dependence
     """
+    casename = case.get_value("CASE")
+    rundir = case.get_value("RUNDIR")
     expect(isdir(rundir), 'Cannot open directory {} '.format(rundir))
-    files = sorted(glob.glob(os.path.join(rundir, casename + '.cpl*.r*.nc')))
+
+    # The MULTI_DRIVER option requires a more careful search for dates.
+    # When True, each date has NINST cpl_####.r files.
+    multidriver = case.get_value('MULTI_DRIVER')
+    logger.debug("_get_datenames:  multidriver = {} ".format(multidriver))
+
+    if multidriver :
+        files = sorted(glob.glob(os.path.join(rundir, casename + '.cpl_0001.r.*.nc')))
+    else:
+        files = sorted(glob.glob(os.path.join(rundir, casename +      '.cpl.r.*.nc')))
+
+    logger.debug("  cpl files : {} ".format(files))
+
     if not files:
         expect(False, 'Cannot find a {}.cpl*.r.*.nc file in directory {} '.format(casename, rundir))
+
     datenames = []
     for filename in files:
         date = get_file_date(filename)
@@ -320,17 +335,17 @@ def _archive_history_files(case, archive, archive_entry,
                                "history file {} does not exist ".format(srcfile))
                         destfile = join(archive_histdir, histfile)
                         if histfile in histfiles_savein_rundir:
-                            logger.info("copying \n{} to \n{} ".format(srcfile, destfile))
+                            logger.debug("histfiles_savein_rundir; copying \n  {} to \n  {} ".format(srcfile, destfile))
                             shutil.copy(srcfile, destfile)
                         else:
-                            logger.info("moving \n{} to \n{} ".format(srcfile, destfile))
+                            logger.debug("_archive_history_files; moving \n  {} to \n  {} ".format(srcfile, destfile))
                             archive_file_fn(srcfile, destfile)
 
 ###############################################################################
 def get_histfiles_for_restarts(rundir, archive, archive_entry, restfile):
 ###############################################################################
     """
-    determine history files that are needed for restarts
+    query restart files to determine history files that are needed for restarts
 
     Not doc-testable due to filesystem dependence
     """
@@ -382,7 +397,7 @@ def _archive_restarts_date(case, archive,
     histfiles_savein_rundir_by_compname = {}
 
     for (archive_entry, compname, compclass) in _get_component_archive_entries(case, archive):
-        logger.info('Archiving restarts for {} ({})'.format(compname, compclass))
+        logger.debug('Archiving restarts for {} ({})'.format(compname, compclass))
 
         # archive restarts
         histfiles_savein_rundir = _archive_restarts_date_comp(case, archive, archive_entry,
@@ -487,7 +502,7 @@ def _archive_restarts_date_comp(case, archive, archive_entry,
                     srcfile = os.path.join(rundir, restfile)
                     destfile = os.path.join(archive_restdir, restfile)
                     last_restart_file_fn(srcfile, destfile)
-                    logger.info("{} {} \n{} to \n{}".format(
+                    logger.debug("{} {} \n  {} to \n  {}".format(
                         "datename_is_last", last_restart_file_fn_msg, srcfile, destfile))
                     for histfile in histfiles_for_restart:
                         srcfile = os.path.join(rundir, histfile)
@@ -495,7 +510,7 @@ def _archive_restarts_date_comp(case, archive, archive_entry,
                         expect(os.path.isfile(srcfile),
                                "history restart file {} for last date does not exist ".format(srcfile))
                         shutil.copy(srcfile, destfile)
-                        logger.info("datename_is_last + histfiles_for_restart copying \n{} to \n{}".format(srcfile, destfile))
+                        logger.debug("datename_is_last + histfiles_for_restart copying \n  {} to \n  {}".format(srcfile, destfile))
                 else:
                     # Only archive intermediate restarts if requested - otherwise remove them
                     if case.get_value('DOUT_S_SAVE_INTERIM_RESTART_FILES'):
@@ -504,7 +519,7 @@ def _archive_restarts_date_comp(case, archive, archive_entry,
                         expect(os.path.isfile(srcfile),
                                "restart file {} does not exist ".format(srcfile))
                         archive_file_fn(srcfile, destfile)
-                        logger.info("moving \n{} to \n{}".format(srcfile, destfile))
+                        logger.debug("_archive_restarts_date_comp; moving \n   {} to \n   {}".format(srcfile, destfile))
 
                         # need to copy the history files needed for interim restarts - since
                         # have not archived all of the history files yet
@@ -514,10 +529,10 @@ def _archive_restarts_date_comp(case, archive, archive_entry,
                             expect(os.path.isfile(srcfile),
                                    "hist file {} does not exist ".format(srcfile))
                             shutil.copy(srcfile, destfile)
-                            logger.info("copying \n{} to \n{}".format(srcfile, destfile))
+                            logger.debug("interim_restarts: copying \n  {} to \n  {}".format(srcfile, destfile))
                     else:
                         srcfile = os.path.join(rundir, restfile)
-                        logger.info("removing interim restart file {}".format(srcfile))
+                        logger.debug("removing interim restart file {}".format(srcfile))
                         if (os.path.isfile(srcfile)):
                             try:
                                 os.remove(srcfile)
@@ -545,7 +560,7 @@ def _archive_process(case, archive, last_date, archive_incomplete_logs, copy_onl
                        archive_incomplete_logs, archive_file_fn)
 
     # archive restarts and all necessary associated files (e.g. rpointer files)
-    datenames = _get_datenames(case.get_value("RUNDIR"), case.get_value("CASE"))
+    datenames = _get_datenames(case)
     histfiles_savein_rundir_by_compname = {}
     for datename in datenames:
         datename_is_last = False
@@ -564,7 +579,7 @@ def _archive_process(case, archive, last_date, archive_incomplete_logs, copy_onl
     for (archive_entry, compname, compclass) in _get_component_archive_entries(case, archive):
         logger.info('Archiving history files for {} ({})'.format(compname, compclass))
         histfiles_savein_rundir = histfiles_savein_rundir_by_compname.get(compname, [])
-        logger.info("histfiles_savein_rundir {} ".format(histfiles_savein_rundir))
+        logger.debug("_archive_process: histfiles_savein_rundir {} ".format(histfiles_savein_rundir))
         _archive_history_files(case, archive, archive_entry,
                                compclass, compname, histfiles_savein_rundir,
                                last_date, archive_file_fn)
@@ -609,7 +624,7 @@ def archive_last_restarts(case, archive_restdir, last_date=None, link_to_restart
     files that are associated with these restart files.)
     """
     archive = case.get_env('archive')
-    datenames = _get_datenames(case.get_value("RUNDIR"), case.get_value("CASE"))
+    datenames = _get_datenames(case)
     expect(len(datenames) >= 1, "No restart dates found")
     last_datename = datenames[-1]
 


Test patch: