def _auto_setup_systems(self, scope, reduced, cgraph): """ Collapse the graph into nodes representing parallel and serial subsystems. """ cgraph = partition_subsystems(scope, reduced, cgraph) if len(cgraph) > 1: if len(cgraph.edges()) > 0: self._system = SerialSystem(scope, reduced, cgraph, tuple(cgraph.nodes())) else: self._system = ParallelSystem(scope, reduced, cgraph, str(tuple(cgraph.nodes()))) elif len(cgraph) == 1: name = cgraph.nodes()[0] self._system = cgraph.node[name].get('system') else: raise RuntimeError("setup_systems called on %s.workflow but component graph is empty!" % self.parent.get_pathname())
def setup_systems(self, system_type): """Get the subsystem for this workflow. Each subsystem contains a subgraph of this workflow's component graph, which contains components and/or other subsystems. """ scope = self.scope drvname = self.parent.name parent_graph = self.scope._reduced_graph reduced = parent_graph.subgraph(parent_graph.nodes_iter()) # collapse driver iteration sets into a single node for # the driver. reduced.collapse_subdrivers(self.parent._iter_set, self.subdrivers()) reduced = reduced.full_subgraph(self.parent._iter_set) params = set() for s in parent_graph.successors(drvname): if parent_graph[drvname][s].get('drv_conn') == drvname: if reduced.in_degree(s): continue params.add(s) reduced.add_node(s[0], comp='param') reduced.add_edge(s[0], s) # we need to connect a param comp node to all param nodes for node in params: param = node[0] reduced.node[param]['system'] = \ ParamSystem(scope, reduced, param) #outs = [] #for p in parent_graph.predecessors(drvname): # if parent_graph[p][drvname].get('drv_conn') == drvname: # outs.append(p) #for out in outs: # vname = out[1][0] # if reduced.out_degree(vname) == 0: # reduced.add_node(vname, comp='dumbvar') # reduced.add_edge(out, vname) # reduced.node[vname]['system'] = \ # VarSystem(scope, reduced, vname) cgraph = reduced.component_graph() opaque_map = {} # map of all internal comps to collapsed # name of opaque system if self.scope._derivs_required: # collapse non-differentiable system groups into # opaque systems systems = {} for group in get_nondiff_groups(reduced, cgraph, self.scope): gtup = tuple(sorted(group)) system = OpaqueSystem(scope, parent_graph, cgraph.subgraph(group), str(gtup)) systems[gtup] = system for gtup, system in systems.items(): collapse_to_system_node(cgraph, system, gtup) reduced.add_node(gtup, comp=True) collapse_nodes(reduced, gtup, reduced.internal_nodes(gtup)) reduced.node[gtup]['comp'] = True reduced.node[gtup]['system'] = system for c in gtup: opaque_map[c] = gtup # get rid of any back edges for opaque boundary nodes that # originate inside of the opaque system to_remove = [] for node in systems: for s in reduced.successors(node): if node in reduced.predecessors(s): to_remove.append((s, node)) reduced.remove_edges_from(to_remove) self._reduced_graph = reduced if system_type == 'auto' and MPI: self._auto_setup_systems(scope, reduced, cgraph) elif MPI and system_type == 'parallel': self._system = ParallelSystem(scope, reduced, cgraph, str(tuple(sorted(cgraph.nodes())))) else: self._system = SerialSystem(scope, reduced, cgraph, str(tuple(sorted(cgraph.nodes())))) self._system.set_ordering([p[0] for p in params]+self._ordering, opaque_map) self._system._parent_system = self.parent._system for comp in self: comp.setup_systems()