def solve_homotopy_gmin2(self, x0, sV): """Newton's method with gmin stepping (nonlinear ports)""" # Adds gmin in parallel with nonlinear element (external) ports # Create Gmin matrix (structure is fixed) Gonesll = pysparse.spmatrix.ll_mat(self.ckt.nD_dimension, self.ckt.nD_dimension) for elem in self.ckt.nD_nlinElem: Gadd = np.eye(len(elem.nD_extPorts)) # import pdb; pdb.set_trace() set_Jac(Gonesll, elem.nD_epos, elem.nD_eneg, elem.nD_epos, elem.nD_eneg, Gadd) Gones = Gonesll.to_csr() tmpVec = np.empty(self.ckt.nD_dimension) def get_deltax(xVec): (iVec, Jac) = self.get_i_Jac(xVec) Gones.matvec(xVec, tmpVec) iVec += self.gmin * tmpVec Jac.shift(self.gmin, Gonesll) return self._get_deltax(iVec - sV, Jac) def f_eval(xVec): iVec = self.get_i(xVec) self.Gones.matvec(xVec, tmpVec) iVec += self.gmin * tmpVec return iVec - sV (x, res, iterations, success) = \ self._homotopy(0.5, self._set_gmin, x0, get_deltax, f_eval) if success: return (x, res, iterations) else: raise NoConvergenceError('gmin stepping did not converge')
def get_i_Jac(self, xVec): """ Calculate total current and Jacobian Returns (iVec, Jac):: iVec = G xVec + i(xVec) Jac = G + (di/dx)(xVec) xVec: input vector of nodal voltages. iVec: output vector of currents Jac: system Jacobian """ # Erase sparse matrix self.Jac.scale(0.) # Linear contribution self.G.matvec(xVec, self.iVec) self.Jac.shift(1., self.Gll) # Nonlinear contribution for elem in self.ckt.nD_nlinElem: # first have to retrieve port voltages from xVec xin = np.zeros(len(elem.controlPorts)) set_xin(xin, elem.nD_vpos, elem.nD_vneg, xVec) (outV, outJac) = elem.eval_and_deriv(xin) # Update iVec and Jacobian now. outV may have extra charge # elements but they are not used in the following set_i(self.iVec, elem.nD_cpos, elem.nD_cneg, outV) set_Jac(self.Jac, elem.nD_cpos, elem.nD_cneg, elem.nD_vpos, elem.nD_vneg, outJac) return (self.iVec, self.Jac)
def refresh(self): """ Re-generate linear matrices Used for parameter sweeps """ self.Gll = pysparse.spmatrix.ll_mat(self.ckt.nD_dimension, self.ckt.nD_dimension) # Generate G matrix (never changes) for elem in self.ckt.nD_elemList: # All elements have nD_linVCCS (perhaps empty) for vccs in elem.nD_linVCCS: set_quad(self.Gll, *vccs) # Frequency-defined elements for elem in self.ckt.nD_freqDefinedElem: set_Jac(self.Gll, elem.nD_fpos, elem.nD_fneg, elem.nD_fpos, elem.nD_fneg, elem.get_G_matrix()) # Free unused memory self.Gll.compress() # Create G in csr form for efficient matrix-vector multiplication self.G = self.Gll.to_csr()