diff --git a/config/xml_schemas/env_mach_pes.xsd b/config/xml_schemas/env_mach_pes.xsd index df6dba2cbbe..7313797c92e 100644 --- a/config/xml_schemas/env_mach_pes.xsd +++ b/config/xml_schemas/env_mach_pes.xsd @@ -6,6 +6,7 @@ + @@ -16,6 +17,7 @@ + diff --git a/scripts/lib/CIME/XML/env_mach_pes.py b/scripts/lib/CIME/XML/env_mach_pes.py index 60e8d8f78ff..6ee18623a12 100644 --- a/scripts/lib/CIME/XML/env_mach_pes.py +++ b/scripts/lib/CIME/XML/env_mach_pes.py @@ -17,6 +17,14 @@ def __init__(self, case_root=None, infile="env_mach_pes.xml", components=None): schema = os.path.join(get_cime_root(), "config", "xml_schemas", "env_mach_pes.xsd") EnvBase.__init__(self, case_root, infile, schema=schema) + def add_comment(self, comment): + if comment is not None: + node = self.make_child("comment", text=comment) + # make_child adds to the end of the file but we want it to follow the header + # so we need to remove it and add it in the correct position + self.remove_child(node) + self.add_child(node, position=1) + def get_value(self, vid, attribute=None, resolved=True, subgroup=None, max_mpitasks_per_node=None): # pylint: disable=arguments-differ # Special variable NINST_MAX is used to determine the number of # drivers in multi-driver mode. diff --git a/scripts/lib/CIME/XML/generic_xml.py b/scripts/lib/CIME/XML/generic_xml.py index 128da821dca..ac763f1e8dc 100644 --- a/scripts/lib/CIME/XML/generic_xml.py +++ b/scripts/lib/CIME/XML/generic_xml.py @@ -44,26 +44,22 @@ def __init__(self, infile=None, schema=None, root_name_override=None, root_attri self.root = None self.locked = False self.read_only = read_only - - if infile == None: - # if file is not defined just return - self.filename = None + self.filename = infile + if infile is None: return if os.path.isfile(infile) and os.access(infile, os.R_OK): # If file is defined and exists, read it - self.filename = infile self.read(infile, schema) else: # if file does not exist create a root xml element # and set it's id to file - expect(not read_only, "Makes no sense to have empty read-only file") - + expect(not self.read_only, "Makes no sense to have empty read-only file") logger.debug("File {} does not exists.".format(infile)) expect("$" not in infile,"File path not fully resolved {}".format(infile)) - self.filename = infile root = _Element(ET.Element("xml")) + if root_name_override: self.root = self.make_child(root_name_override, root=root, attributes=root_attrib_override) else: @@ -170,13 +166,16 @@ def name(self, node): def text(self, node): return node.xml_element.text - def add_child(self, node, root=None): + def add_child(self, node, root=None, position=None): """ Add element node to self at root """ expect(not self.locked and not self.read_only, "locked") root = root if root is not None else self.root - root.xml_element.append(node.xml_element) + if position is not None: + root.xml_element.insert(position, node.xml_element) + else: + root.xml_element.append(node.xml_element) def copy(self, node): return deepcopy(node) diff --git a/scripts/lib/CIME/XML/pes.py b/scripts/lib/CIME/XML/pes.py index 52d53d6a387..4e6d8522e0d 100644 --- a/scripts/lib/CIME/XML/pes.py +++ b/scripts/lib/CIME/XML/pes.py @@ -28,11 +28,14 @@ def find_pes_layout(self, grid, compset, machine, pesize_opts='M', mpilib=None): oother_settings = {} other_settings = {} o_grid_nodes = [] + comments = None # Get any override nodes overrides = self.get_optional_child("overrides") + ocomments = None if overrides is not None: o_grid_nodes = self.get_children("grid", root = overrides) - opes_ntasks, opes_nthrds, opes_rootpe, opes_pstrid, oother_settings = self._find_matches(o_grid_nodes, grid, compset, machine, pesize_opts, True) + opes_ntasks, opes_nthrds, opes_rootpe, opes_pstrid, oother_settings, ocomments = self._find_matches(o_grid_nodes, grid, compset, machine, pesize_opts, True) + # Get all the nodes grid_nodes = self.get_children("grid") if o_grid_nodes: @@ -42,12 +45,15 @@ def find_pes_layout(self, grid, compset, machine, pesize_opts='M', mpilib=None): grid_nodes = list(gn_set) - pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings = self._find_matches(grid_nodes, grid, compset, machine, pesize_opts, False) + pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings, comments = self._find_matches(grid_nodes, grid, compset, machine, pesize_opts, False) pes_ntasks.update(opes_ntasks) pes_nthrds.update(opes_nthrds) pes_rootpe.update(opes_rootpe) pes_pstrid.update(opes_pstrid) other_settings.update(oother_settings) + if ocomments is not None: + comments = ocomments + if mpilib == "mpi-serial": for i in iter(pes_ntasks): @@ -64,7 +70,10 @@ def find_pes_layout(self, grid, compset, machine, pesize_opts='M', mpilib=None): logger.info("Pes setting: rootpe is {} ".format(pes_rootpe)) logger.info("Pes setting: pstrid is {} ".format(pes_pstrid)) logger.info("Pes other settings: {}".format(other_settings)) - return pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings + if comments is not None: + logger.info("Pes comments: {}".format(comments)) + + return pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings, comments def _find_matches(self, grid_nodes, grid, compset, machine, pesize_opts, override=False): grid_choice = None @@ -74,6 +83,7 @@ def _find_matches(self, grid_nodes, grid, compset, machine, pesize_opts, overrid max_points = -1 pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings = {}, {}, {}, {}, {} pe_select = None + comment = None for grid_node in grid_nodes: grid_match = self.get(grid_node, "name") if grid_match == "any" or re.search(grid_match,grid): @@ -96,7 +106,9 @@ def _find_matches(self, grid_nodes, grid, compset, machine, pesize_opts, overrid for node in self.get_children(root=pes_node): vid = self.name(node) logger.info("vid is {}".format(vid)) - if "ntasks" in vid: + if "comment" in vid: + comment = self.text(node) + elif "ntasks" in vid: for child in self.get_children(root=node): pes_ntasks[self.name(child).upper()] = int(self.text(child)) elif "nthrds" in vid: @@ -131,7 +143,9 @@ def _find_matches(self, grid_nodes, grid, compset, machine, pesize_opts, overrid for node in self.get_children(root=pe_select): vid = self.name(node) logger.debug("vid is {}".format(vid)) - if "ntasks" in vid: + if "comment" in vid: + comment = self.text(node) + elif "ntasks" in vid: for child in self.get_children(root=node): pes_ntasks[self.name(child).upper()] = int(self.text(child)) elif "nthrds" in vid: @@ -144,7 +158,7 @@ def _find_matches(self, grid_nodes, grid, compset, machine, pesize_opts, overrid for child in self.get_children(root=node): pes_pstrid[self.name(child).upper()] = int(self.text(child)) # if the value is already upper case its something else we are trying to set - elif vid == self.name(node) and vid != "comment": + elif vid == self.name(node): other_settings[vid] = self.text(node) if grid_choice != 'any' or logger.isEnabledFor(logging.DEBUG): logger.info("Pes setting: grid match is {} ".format(grid_choice )) @@ -155,4 +169,4 @@ def _find_matches(self, grid_nodes, grid, compset, machine, pesize_opts, overrid if pesize_choice != 'any' or logger.isEnabledFor(logging.DEBUG): logger.info("Pes setting: pesize match is {} ".format(pesize_choice)) - return pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings + return pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other_settings, comment diff --git a/scripts/lib/CIME/case.py b/scripts/lib/CIME/case.py index 9f47e181c37..b151ad125b2 100644 --- a/scripts/lib/CIME/case.py +++ b/scripts/lib/CIME/case.py @@ -671,7 +671,7 @@ def _setup_mach_pes(self, pecount, multi_driver, ninst, machine_name, mpilib): pes_rootpe = {} pes_pstrid = {} other = {} - + comment = None force_tasks = None force_thrds = None @@ -687,7 +687,7 @@ def _setup_mach_pes(self, pecount, multi_driver, ninst, machine_name, mpilib): force_tasks = int(match2.group(1)) pes_nthrds = pesobj.find_pes_layout(self._gridname, self._compsetname, machine_name, mpilib=mpilib)[1] else: - pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other = pesobj.find_pes_layout(self._gridname, self._compsetname, + pes_ntasks, pes_nthrds, pes_rootpe, pes_pstrid, other, comment = pesobj.find_pes_layout(self._gridname, self._compsetname, machine_name, pesize_opts=pecount, mpilib=mpilib) if match1 or match2: @@ -705,6 +705,7 @@ def _setup_mach_pes(self, pecount, multi_driver, ninst, machine_name, mpilib): pes_rootpe[string_] = 0 mach_pes_obj = self.get_env("mach_pes") + mach_pes_obj.add_comment(comment) if other is not None: for key, value in other.items():