def linearize(self, params, unknowns, resids): """ Uses complex step method to calculate a Jacobian dict. Args ---- params : `VecWrapper` `VecWrapper` containing parameters. (p) unknowns : `VecWrapper` `VecWrapper` containing outputs and states. (u) resids : `VecWrapper` `VecWrapper` containing residuals. (r) Returns ------- dict Dictionary whose keys are tuples of the form ('unknown', 'param') and whose values are ndarrays. """ # our complex step step = self.complex_stepsize * 1j J = OrderedDict() non_pbo_unknowns = self._non_pbo_unknowns for param in params: pwrap = _TmpDict(params) pval = params[param] if isinstance(pval, ndarray): # replace the param array with a complex copy pwrap[param] = numpy.asarray(pval, complex) idx_iter = array_idx_iter(pwrap[param].shape) psize = pval.size else: pwrap[param] = complex(pval) idx_iter = (None, ) psize = 1 for i, idx in enumerate(idx_iter): # set a complex param value if idx is None: pwrap[param] += step else: pwrap[param][idx] += step uwrap = _TmpDict(unknowns, complex=True) # solve with complex param value self.solve_nonlinear(pwrap, uwrap, resids) for u in non_pbo_unknowns: jval = imag(uwrap[u] / self.complex_stepsize) if (u, param) not in J: # create the dict entry J[(u, param)] = numpy.zeros((jval.size, psize)) # set the column in the Jacobian entry J[(u, param)][:, i] = jval.flat # restore old param value if idx is None: pwrap[param] -= step else: pwrap[param][idx] -= step return J
def linearize(self, params, unknowns, resids): """ Uses complex step method to calculate a Jacobian dict. Args ---- params : `VecWrapper` `VecWrapper` containing parameters. (p) unknowns : `VecWrapper` `VecWrapper` containing outputs and states. (u) resids : `VecWrapper` `VecWrapper` containing residuals. (r) Returns ------- dict Dictionary whose keys are tuples of the form ('unknown', 'param') and whose values are ndarrays. """ # our complex step step = self.complex_stepsize * 1j J = OrderedDict() non_pbo_unknowns = self._non_pbo_unknowns for param in params: pwrap = _TmpDict(params) pval = params[param] if isinstance(pval, ndarray): # replace the param array with a complex copy pwrap[param] = numpy.asarray(pval, complex) idx_iter = array_idx_iter(pwrap[param].shape) psize = pval.size else: pwrap[param] = complex(pval) idx_iter = (None,) psize = 1 for i, idx in enumerate(idx_iter): # set a complex param value if idx is None: pwrap[param] += step else: pwrap[param][idx] += step uwrap = _TmpDict(unknowns, complex=True) # solve with complex param value self.solve_nonlinear(pwrap, uwrap, resids) for u in non_pbo_unknowns: jval = imag(uwrap[u] / self.complex_stepsize) if (u, param) not in J: # create the dict entry J[(u, param)] = numpy.zeros((jval.size, psize)) # set the column in the Jacobian entry J[(u, param)][:, i] = jval.flat # restore old param value if idx is None: pwrap[param] -= step else: pwrap[param][idx] -= step return J