예제 #1
0
    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
예제 #3
0
 def applyJT(self, system, variables):
     """ Wrapper for component derivative specification methods.
     Adjoint Mode.
     """
     applyJT(system, variables)
예제 #4
0
 def applyJT(self, system, variables):
     """ Wrapper for component derivative specification methods.
     Adjoint Mode.
     """
     applyJT(system, variables)