def add_to_graph(self, startgraph, dgraph, excludes=()): """Add this PseudoAssembly to the given graph, absorbing nodes that represent components contained in this PA. """ from openmdao.main.depgraph import is_subvar_node, \ is_input_base_node, is_output_base_node self._removed_comps = [c for c in self.comps if c not in excludes] # Add pseudoassys to graph dgraph.add_node(self.name, pa_object=self, comp=True, pseudo='assembly', valid=True) empty = {} for oldname, newname in self.renames.items(): attrs = startgraph.node.get(oldname, empty).copy() if oldname in self.boundary_params: attrs['iotype'] = 'out' dgraph.add_node(newname, attr_dict=attrs) for u, v, data in dgraph.edges(oldname, data=True): dgraph.add_edge(newname, v, attr_dict=data.copy()) for u, v, data in dgraph.in_edges(oldname, data=True): dgraph.add_edge(u, newname, attr_dict=data.copy()) if is_subvar_node(dgraph, newname): dgraph.node[newname]['basevar'] = \ newname.split('[', 1)[0] if is_input_base_node(dgraph, newname): dgraph.add_edge(newname, self.name) elif is_output_base_node(dgraph, newname): dgraph.add_edge(self.name, newname)
def add_to_graph(self, startgraph, dgraph, excludes=()): """Add this PseudoAssembly to the given graph, absorbing nodes that represent components contained in this PA. """ from openmdao.main.depgraph import is_subvar_node, is_input_base_node, is_output_base_node self._removed_comps = [c for c in self.comps if c not in excludes] # Add pseudoassys to graph dgraph.add_node(self.name, pa_object=self, comp=True, pseudo="assembly", valid=True) empty = {} for oldname, newname in self.renames.items(): attrs = startgraph.node.get(oldname, empty).copy() if oldname in self.boundary_params: attrs["iotype"] = "out" dgraph.add_node(newname, attr_dict=attrs) for u, v, data in dgraph.edges(oldname, data=True): dgraph.add_edge(newname, v, attr_dict=data.copy()) for u, v, data in dgraph.in_edges(oldname, data=True): dgraph.add_edge(u, newname, attr_dict=data.copy()) if is_subvar_node(dgraph, newname): dgraph.node[newname]["basevar"] = newname.split("[", 1)[0] if is_input_base_node(dgraph, newname): dgraph.add_edge(newname, self.name) elif is_output_base_node(dgraph, newname): dgraph.add_edge(self.name, newname) dgraph.config_changed()
def matvecREV(self, arg): '''Callback function for performing the matrix vector product of the workflow's full Jacobian with an incoming vector arg.''' dgraph = self._derivative_graph comps = self._comp_edge_list() result = zeros(len(arg)) # We can call applyJ on each component one-at-a-time, and poke the # results into the result vector. for compname, data in comps.iteritems(): if compname == '@fake': continue comp_inputs = data['inputs'] comp_outputs = data['outputs'] comp_residuals = data['residuals'] inputs = {} outputs = {} out_bounds = [] for varname in comp_outputs: node = '%s.%s' % (compname, varname) # Ouputs define unique edges, so don't duplicate anything if is_subvar_node(dgraph, node): if dgraph.base_var(node).split('.', 1)[1] in comp_outputs: continue i1, i2 = self.get_bounds(node) if isinstance(i1, list): inputs[varname] = arg[i1].copy() if varname not in comp_residuals: outputs[varname] = zeros(len(i1)) out_bounds.append((varname, i1, i2)) else: inputs[varname] = arg[i1:i2].copy() if varname not in comp_residuals: outputs[varname] = zeros(i2 - i1) out_bounds.append((varname, i1, i2)) for varname in comp_inputs: node = '%s.%s' % (compname, varname) i1, i2 = self.get_bounds(node) if isinstance(i1, list): outputs[varname] = zeros(len(i1)) else: outputs[varname] = zeros(i2 - i1) out_bounds.append((varname, i1, i2)) if '~' in compname: comp = self._derivative_graph.node[compname]['pa_object'] else: comp = self.scope.get(compname) # Preconditioning if hasattr(comp, 'applyMinvT'): inputs = applyMinvT(comp, inputs, self._shape_cache) applyJT(comp, inputs, outputs, comp_residuals, self._shape_cache, self._J_cache.get(compname)) #print inputs, outputs for varname, i1, i2 in out_bounds: if isinstance(i1, list): result[i1] += outputs[varname] else: result[i1:i2] += outputs[varname] # Each parameter adds an equation for src, target in self._edges.iteritems(): if '@in' in src or '@fake' in src: if isinstance(target, list): target = target[0] i1, i2 = self.get_bounds(target) result[i1:i2] += arg[i1:i2] # A fake output needs to make it into the result vector to prevent # the solution from blowing up. Its derivative will be zero # regardless. if '@fake' in target: i1, i2 = self.get_bounds(src) result[i1:i2] += arg[i1:i2] #print arg, result return result
def matvecREV(self, arg): '''Callback function for performing the matrix vector product of the workflow's full Jacobian with an incoming vector arg.''' dgraph = self._derivative_graph comps = self._comp_edge_list() result = zeros(len(arg)) # We can call applyJ on each component one-at-a-time, and poke the # results into the result vector. for compname, data in comps.iteritems(): if compname == '@fake': continue comp_inputs = data['inputs'] comp_outputs = data['outputs'] comp_residuals = data['residuals'] inputs = {} outputs = {} out_bounds = [] for varname in comp_outputs: node = '%s.%s' % (compname, varname) # Ouputs define unique edges, so don't duplicate anything if is_subvar_node(dgraph, node): if dgraph.base_var(node).split('.', 1)[1] in comp_outputs: continue i1, i2 = self.get_bounds(node) if isinstance(i1, list): inputs[varname] = arg[i1].copy() if varname not in comp_residuals: outputs[varname] = zeros(len(i1)) out_bounds.append((varname, i1, i2)) else: inputs[varname] = arg[i1:i2].copy() if varname not in comp_residuals: outputs[varname] = zeros(i2-i1) out_bounds.append((varname, i1, i2)) for varname in comp_inputs: node = '%s.%s' % (compname, varname) i1, i2 = self.get_bounds(node) if isinstance(i1, list): outputs[varname] = zeros(len(i1)) else: outputs[varname] = zeros(i2-i1) out_bounds.append((varname, i1, i2)) if '~' in compname: comp = self._derivative_graph.node[compname]['pa_object'] else: comp = self.scope.get(compname) # Preconditioning if hasattr(comp, 'applyMinvT'): inputs = applyMinvT(comp, inputs, self._shape_cache) applyJT(comp, inputs, outputs, comp_residuals, self._shape_cache, self._J_cache.get(compname)) #print inputs, outputs for varname, i1, i2 in out_bounds: if isinstance(i1, list): result[i1] += outputs[varname] else: result[i1:i2] += outputs[varname] # Each parameter adds an equation for src, target in self._edges.iteritems(): if '@in' in src or '@fake' in src: if isinstance(target, list): target = target[0] i1, i2 = self.get_bounds(target) result[i1:i2] += arg[i1:i2] #print arg, result return result