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
def applyJT(self, system, variables): """ Wrapper for component derivative specification methods. Adjoint Mode. """ applyJT(system, variables)