def calc_gradient(self, inputs, outputs, return_format='dict'):
        """Returns a nested dict of sensitivities if return_format == 'dict'.
        """

        system = self._system
        options = self.options
        name2collapsed = system.scope.name2collapsed

        inputs = [fix_single_tuple(x) for x in inputs]
        outputs = [fix_single_tuple(x) for x in outputs]

        if return_format == 'dict':
            J = {}
            for okey in outputs:
                J[okey] = {}
                for ikey in inputs:
                    if isinstance(ikey, tuple):
                        ikey = ikey[0]
                    J[okey][ikey] = None
        else:
            num_input = system.get_size(inputs)
            num_output = system.get_size(outputs)
            J = np.zeros((num_output, num_input))

        if system.mode == 'adjoint':
            outputs, inputs = inputs, outputs

        self.ksp.setTolerances(max_it=options.maxiter,
                               atol=options.atol,
                               rtol=options.rtol)

        j = 0
        for param in inputs:

            if isinstance(param, tuple):
                param = param[0]

            param_tup = name2collapsed[param]
            param_size = system.get_size(param)

            jbase = j

            # Did the user define a custom Jacobian for a constraint?
            if system.mode == 'adjoint' and param in self.custom_jacs:
                self.user_defined_jacobian(param, outputs, J)
                j += param_size
                continue

            for irhs in xrange(param_size):

                # Solve the system with PetSC KSP
                solvec = system._compute_derivatives(param_tup, irhs)

                i = 0
                for out in outputs:

                    if isinstance(out, tuple):
                        out = out[0]

                    out_size = system.get_size(out)

                    if return_format == 'dict':
                        if system.mode == 'forward':
                            if out in solvec:
                                if J[out][param] is None:
                                    J[out][param] = np.zeros((out_size, param_size))
                                J[out][param][:, j-jbase] = solvec[out]
                            else:
                                del J[out][param]
                        else:
                            if out in solvec:
                                if J[param][out] is None:
                                    J[param][out] = np.zeros((param_size, out_size))
                                J[param][out][j-jbase, :] = solvec[out]
                            else:
                                del J[param][out]

                    else:
                        if out in solvec:
                            nk = len(solvec[out])
                            if system.mode == 'forward':
                                J[i:i+nk, j] = solvec[out]
                            else:
                                J[j, i:i+nk] = solvec[out]
                            i += nk
                j += 1

        return J
dataset/ETHPy150Open OpenMDAO/OpenMDAO-Framework/openmdao.main/src/openmdao/main/linearsolver.py/PETSc_KSP.calc_gradient/original