Repository: ESMCI/cime

Issue:
Need testcase to replace ERS_IOP
Going to call it IOP.



Discussion:
Can we call it something else?

Sure, what would you like?

I liked "ERIO"

That implies exact restart. We're not actually doing a restart, just doing two runs with different PIO settings.

Then how about "SMIO"?  A smoke test with two different PIO settings.

So you are just doing two initial runs with different PIO settings?   I think that including a restart in there is important since writing and reading restart files is an important aspect of the io subsystem.

There are currently 4 supported PIO methods

netcdf (serial)
netcdf4p (hdf5 paralllel)
netcdf4c  (hdf5 compressed serial)
pnetcdf    (parallel)

Ideally the test would write and read restart files with each of these possibilities - it might even be good if they were written with one and read with each of the others - how many permutations is that?

I think that is only 16 tests (each one writes followed by 4 reads).
Maybe we should call the **E**xact **I**op **E**very **IO** test (EIEIO).

Thanks for the feedback. EIEIO is kinda catchy, reminds me of old McDonald.

Glad you caught the reference, it took a lot of effort to come up with that acronym :)

So do we really want EIEIO over ERIO?

ERIO please

On Mon, Aug 1, 2016 at 11:29 AM, James Foucar notifications@github.com
wrote:

> So do we really want EIEIO over ERIO?
> 
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> https://github.com/ESMCI/cime/issues/306#issuecomment-236649011, or mute
> the thread
> https://github.com/notifications/unsubscribe-auth/AF16GC2OTVsXBThiGa-k5R7xXFaYxQ3hks5qbiz5gaJpZM4JYcBU
> .

## 

Jim Edwards

CESM Software Engineer
National Center for Atmospheric Research
Boulder, CO


Resolving patch:
diff --git a/utils/python/CIME/SystemTests/erio.py b/utils/python/CIME/SystemTests/erio.py
new file mode 100644
--- /dev/null
+++ b/utils/python/CIME/SystemTests/erio.py
@@ -0,0 +1,115 @@
+"""
+ERIO tests restart with different PIO methods
+
+This class inherits from SystemTestsCommon
+"""
+from CIME.XML.standard_module_setup import *
+from CIME.SystemTests.system_tests_common import SystemTestsCommon
+import shutil
+
+logger = logging.getLogger(__name__)
+
+class ERIO(SystemTestsCommon):
+
+    def __init__(self, case):
+        """
+        initialize an object interface to file env_test.xml in the case directory
+        """
+        SystemTestsCommon.__init__(self, case, expected=["TEST"])
+
+        self._pio_types = self._case.get_env("run").get_valid_values("PIO_TYPENAME")
+
+    def build_phase(self, sharedlib_only=False, model_only=False):
+        """
+        Build one executable per PIO method
+        """
+        exeroot = self._case.get_value("EXEROOT")
+        cime_model = self._case.get_value("MODEL")
+
+        for pio_type in self._pio_types:
+            if pio_type == "default":
+                continue
+            else:
+                self._case.set_value("PIO_TYPENAME", pio_type)
+                self._case.flush()
+
+                self.clean_build()
+                self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only)
+                if sharedlib_only:
+                    continue
+
+                logger.info("doing a build with pio type %s" % pio_type)
+
+                shutil.move("%s/%s.exe" % (exeroot, cime_model),
+                            "%s/%s.exe.%s" % (exeroot, cime_model, pio_type))
+
+    def _full_run(self, pio_type):
+        exeroot = self._case.get_value("EXEROOT")
+        cime_model = self._case.get_value("MODEL")
+
+        base_exe_path = "%s/%s.exe" % (exeroot, cime_model)
+        pio_exe_path  = "%s/%s.exe.%s" % (exeroot, cime_model, pio_type)
+
+        if os.path.exists(base_exe_path):
+            os.remove(base_exe_path)
+
+        shutil.copy(pio_exe_path, base_exe_path)
+
+        stop_n      = self._case.get_value("STOP_N")
+        stop_option = self._case.get_value("STOP_OPTION")
+        expect(stop_n > 0, "Bad STOP_N: %d" % stop_n)
+
+        # Move to config_tests.xml once that's ready
+        rest_n = stop_n/2 + 1
+        self._case.set_value("REST_N", rest_n)
+        self._case.set_value("REST_OPTION", 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.flush()
+
+        expect(stop_n > 2, "ERROR: stop_n value %d too short"%stop_n)
+        logger.info("doing an %s %s initial test with restart file at %s %s with pio type %s"
+                    %(str(stop_n), stop_option, str(rest_n), stop_option, pio_type))
+        self.run_indv(suffix=pio_type)
+
+    def _restart_run(self, pio_type, other_pio_type):
+        exeroot = self._case.get_value("EXEROOT")
+        cime_model = self._case.get_value("MODEL")
+
+        base_exe_path = "%s/%s.exe" % (exeroot, cime_model)
+        pio_exe_path  = "%s/%s.exe.%s" % (exeroot, cime_model, pio_type)
+
+        if os.path.exists(base_exe_path):
+            os.remove(base_exe_path)
+
+        shutil.copy(pio_exe_path, base_exe_path)
+
+        stop_n      = self._case.get_value("STOP_N")
+        stop_option = self._case.get_value("STOP_OPTION")
+
+        rest_n = stop_n/2 + 1
+        stop_new = stop_n - rest_n
+        expect(stop_new > 0, "ERROR: stop_n value %d too short %d %d"%(stop_new,stop_n,rest_n))
+
+        self._case.set_value("STOP_N", stop_new)
+        self._case.set_value("CONTINUE_RUN", True)
+        self._case.set_value("REST_OPTION","never")
+        self._case.flush()
+        logger.info("doing an %s %s restart test with %s against %s"
+                    %(str(stop_n), stop_option, pio_type, other_pio_type))
+
+        suffix = "%s.%s" % (other_pio_type, pio_type)
+        self.run_indv(suffix=suffix)
+
+        # Compare restart file
+        self._component_compare_test(other_pio_type, suffix)
+
+    def run_phase(self):
+
+        for idx, pio_type1 in enumerate(self._pio_types):
+            if pio_type1 != "default":
+                self._full_run(pio_type1)
+                for pio_type2 in self._pio_types[idx+1:]:
+                    if pio_type2 != "default":
+                        self._restart_run(pio_type2, pio_type1)
diff --git a/utils/python/CIME/XML/entry_id.py b/utils/python/CIME/XML/entry_id.py
--- a/utils/python/CIME/XML/entry_id.py
+++ b/utils/python/CIME/XML/entry_id.py
@@ -140,6 +140,17 @@ def _get_description (self, node):
     def _get_group (self, node):
         return self._get_node_element_info(node, "group")
 
+    def get_valid_values(self, vid):
+        node = self.get_optional_node("entry", {"id":vid})
+        if node is None:
+            return None
+
+        vv_node = self.get_optional_node("valid_values", root=node)
+        if vv_node is None:
+            return None
+        else:
+            return vv_node.text.split(",")
+
     def set_valid_values(self, vid, new_valid_values):
         node = self.get_optional_node("entry", {"id":vid})
         if node is None:


Test patch:
diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml
--- a/cime_config/config_tests.xml
+++ b/cime_config/config_tests.xml
@@ -205,6 +205,15 @@ LII    CLM initial condition interpolation test
     <CONTINUE_RUN>FALSE</CONTINUE_RUN>
   </test>
 
+  <test NAME="ERIO">
+    <DESC>exact restart from startup with different PIO methods, default 6 days + 5 days</DESC>
+    <INFO_DBUG>1</INFO_DBUG>
+    <STOP_OPTION>ndays</STOP_OPTION>
+    <STOP_N>11</STOP_N>
+    <DOUT_S>FALSE</DOUT_S>
+    <CONTINUE_RUN>FALSE</CONTINUE_RUN>
+  </test>
+
   <test NAME="ERR">
     <DESC>exact restart from startup with resubmit, default 4 days + 3 days</DESC>
     <INFO_DBUG>1</INFO_DBUG>
diff --git a/utils/python/update_acme_tests.py b/utils/python/update_acme_tests.py
--- a/utils/python/update_acme_tests.py
+++ b/utils/python/update_acme_tests.py
@@ -41,6 +41,7 @@
     "cime_developer" : (None,
                             ("NCK_Ld3.f45_g37_rx1.A",
                              "ERI.f45_g37.X",
+                             "ERIO.f45_g37.X",
                              "SEQ_Ln9.f19_g16_rx1.A",
                              "ERS_Ld3.ne30_g16_rx1.A",
                              "ERS_N2_Ld3.f19_g16_rx1.A",