def first_time_step(system): """Compute the first time step""" settings = system.TDS if not system.DAE.n: freq = 1.0 elif system.DAE.n == 1: B = matrix(system.DAE.Gx) linsolve(system.DAE.Gy, B) As = system.DAE.Fx - system.DAE.Fy * B freq = abs(As[0, 0]) else: freq = 20.0 if freq > system.Settings.freq: freq = float(system.Settings.freq) tspan = abs(settings.tf - settings.t0) tcycle = 1 / freq settings.deltatmax = min(5 * tcycle, tspan / 100.0) settings.deltat = min(tcycle, tspan / 100.0) settings.deltatmin = min(tcycle / 64, settings.deltatmax / 20) if settings.fixt: if settings.tstep <= 0: system.Log.warning('Fixed time step is negative or zero') system.Log.warning('Switching to automatic time step') settings.fixt = False else: settings.deltat = settings.tstep if settings.tstep < settings.deltatmin: system.Log.warning( 'Fixed time step is below the estimated minimum') return settings.deltat
def linsolve(self, A, b): """ Solve linear equation set ``Ax = b`` and returns the solutions in a 1-D array. This function performs both symbolic and numeric factorizations every time, and can be slower than ``Solver.solve``. Parameters ---------- A Sparse matrix b RHS of the equation Returns ------- The solution in a 1-D np array. """ if self.sparselib == 'umfpack': try: umfpack.linsolve(A, b) except ArithmeticError: logger.error('Singular matrix. Case is not solvable') return np.ravel(b) elif self.sparselib == 'klu': try: klu.linsolve(A, b) except ArithmeticError: logger.error('Singular matrix. Case is not solvable') return np.ravel(b) elif self.sparselib in ('spsolve', 'cupy'): ccs = A.CCS size = A.size data = np.array(ccs[2]).reshape((-1, )) indices = np.array(ccs[1]).reshape((-1, )) indptr = np.array(ccs[0]).reshape((-1, )) A = csc_matrix((data, indices, indptr), shape=size) if self.sparselib == 'spsolve': x = spsolve(A, b) return np.ravel(x) elif self.sparselib == 'cupy': # delayed import for startup speed import cupy as cp # NOQA from cupyx.scipy.sparse import csc_matrix as csc_cu # NOQA from cupyx.scipy.sparse.linalg.solve import lsqr as cu_lsqr # NOQA cu_A = csc_cu(A) cu_b = cp.array(np.array(b).reshape((-1, ))) x = cu_lsqr(cu_A, cu_b) return np.ravel(cp.asnumpy(x[0]))
def klu_linsolve(A, b): """ KLU wrapper function for linear system solve A x = b :param A: System matrix :param b: right hand side :return: solution """ A2 = A.tocoo() A_cvxopt = cvxopt.spmatrix(A2.data, A2.row, A2.col, A2.shape, 'd') x = cvxopt.matrix(b) klu.linsolve(A_cvxopt, x) return np.array(x)[:, 0]
def linsolve(self, A, b): """ Solve linear equation set ``Ax = b`` and store the solutions in ``b``. Parameters ---------- A Sparse matrix b RHS of the equation Returns ------- None """ if self.sparselib == 'umfpack': umfpack.linsolve(A, b) return b elif self.sparselib == 'klu': klu.linsolve(A, b) return b elif self.sparselib in ('spsolve', 'cupy'): ccs = A.CCS size = A.size data = np.array(ccs[2]).reshape((-1, )) indices = np.array(ccs[1]).reshape((-1, )) indptr = np.array(ccs[0]).reshape((-1, )) A = csc_matrix((data, indices, indptr), shape=size) if self.sparselib == 'spsolve': x = spsolve(A, b) return matrix(x) elif self.sparselib == 'cupy': # delayed import for startup speed import cupy as cp # NOQA from cupyx.scipy.sparse import csc_matrix as csc_cu # NOQA from cupyx.scipy.sparse.linalg.solve import lsqr as cu_lsqr # NOQA cu_A = csc_cu(A) cu_b = cp.array(np.array(b).reshape((-1, ))) x = cu_lsqr(cu_A, cu_b) return matrix(cp.asnumpy(x[0]))
def linsolve(self, A, b): """ Solve linear equation set ``Ax = b`` and store the solutions in ``b``. Parameters ---------- A Sparse matrix b RHS of the equation Returns ------- None """ if self.sparselib == 'umfpack': return umfpack.linsolve(A, b) elif self.sparselib == 'klu': return klu.linsolve(A, b)
def init1(self, dae): """New initialization function""" self.servcall(dae) retval = True mva = self.system.mva self.p0 = mul(self.p0, self.gammap) self.q0 = mul(self.q0, self.gammaq) dae.y[self.vsd] = mul(dae.y[self.v], -sin(dae.y[self.a])) dae.y[self.vsq] = mul(dae.y[self.v], cos(dae.y[self.a])) rs = matrix(self.rs) rr = matrix(self.rr) xmu = matrix(self.xmu) x1 = matrix(self.xs) + xmu x2 = matrix(self.xr) + xmu Pg = matrix(self.p0) Qg = matrix(self.q0) Vc = dae.y[self.v] vsq = dae.y[self.vsq] vsd = dae.y[self.vsd] toSn = div(mva, self.Sn) # to machine base toSb = self.Sn / mva # to system base # rotor speed omega = 1 * (ageb(mva * Pg, self.Sn)) + \ mul(0.5 + 0.5 * mul(Pg, toSn), aandb(agtb(Pg, 0), altb(mva * Pg, self.Sn))) + \ 0.5 * (aleb(mva * Pg, 0)) slip = 1 - omega theta = mul(self.Kp, mround(1000 * (omega - 1)) / 1000) theta = mmax(theta, 0) # prepare for the iterations irq = mul(-x1, toSb, (2 * omega - 1), div(1, Vc), div(1, xmu), div(1, omega)) isd = zeros(*irq.size) isq = zeros(*irq.size) # obtain ird isd isq for i in range(self.n): A = sparse([[-rs[i], vsq[i]], [x1[i], -vsd[i]]]) B = matrix([vsd[i] - xmu[i] * irq[i], Qg[i]]) linsolve(A, B) isd[i] = B[0] isq[i] = B[1] ird = -div(vsq + mul(rs, isq) + mul(x1, isd), xmu) vrd = -mul(rr, ird) + mul( slip, mul(x2, irq) + mul(xmu, isq)) # todo: check x1 or x2 vrq = -mul(rr, irq) - mul(slip, mul(x2, ird) + mul(xmu, isd)) # main iterations for i in range(self.n): mis = ones(6, 1) rows = [0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5] cols = [0, 1, 3, 0, 1, 2, 2, 4, 3, 5, 0, 1, 2] x = matrix([isd[i], isq[i], ird[i], irq[i], vrd[i], vrq[i]]) # vals = [-rs, x1, xmu, -x1, -rs, -xmu, -rr, # -1, -rr, -1, vsd, vsq, -xmu * Vc / x1] vals = [ -rs[i], x1[i], xmu[i], -x1[i], -rs[i], -xmu[i], -rr[i], -1, -rr[i], -1, vsd[i], vsq[i], -xmu[i] * Vc[i] / x1[i] ] jac0 = spmatrix(vals, rows, cols, (6, 6), 'd') niter = 0 while max(abs(mis)) > self.system.tds.config.tol: if niter > 20: logger.error('Initialization of DFIG <{}> failed.'.format( self.name[i])) retval = False break mis[0] = -rs[i] * x[0] + x1[i] * x[1] + xmu[i] * x[3] - vsd[i] mis[1] = -rs[i] * x[1] - x1[i] * x[0] - xmu[i] * x[2] - vsq[i] mis[2] = -rr[i] * x[2] + slip[i] * (x2[i] * x[3] + xmu[i] * x[1]) - x[4] mis[3] = -rr[i] * x[3] - slip[i] * (x2[i] * x[2] + xmu[i] * x[0]) - x[5] mis[4] = vsd[i] * x[0] + vsq[i] * x[1] + x[4] * x[2] + \ x[5] * x[3] - Pg[i] mis[5] = -xmu[i] * Vc[i] * x[2] / x1[i] - \ Vc[i] * Vc[i] / x1[i] - Qg[i] rows = [2, 2, 3, 3, 4, 4, 4, 4] cols = [1, 3, 0, 2, 2, 3, 4, 5] vals = [ slip[i] * xmu[i], slip[i] * x2[i], -slip[i] * xmu[i], -slip[i] * x2[i], x[4], x[5], x[2], x[3] ] jac = jac0 + spmatrix(vals, rows, cols, (6, 6), 'd') linsolve(jac, mis) x -= mis niter += 1 isd[i] = x[0] isq[i] = x[1] ird[i] = x[2] irq[i] = x[3] vrd[i] = x[4] vrq[i] = x[5] dae.x[self.ird] = mul(self.u0, ird) dae.x[self.irq] = mul(self.u0, irq) dae.y[self.isd] = isd dae.y[self.isq] = isq dae.y[self.vrd] = vrd dae.y[self.vrq] = vrq dae.x[self.omega_m] = mul(self.u0, omega) dae.x[self.theta_p] = mul(self.u0, theta) dae.y[self.pwa] = mmax(mmin(2 * dae.x[self.omega_m] - 1, 1), 0) self.vref0 = mul(aneb(self.KV, 0), Vc - div(ird + div(Vc, xmu), self.KV)) dae.y[self.vref] = self.vref0 k = mul(div(x1, Vc, xmu, omega), toSb) self.irq_off = -mul(k, mmax(mmin(2 * omega - 1, 1), 0)) - irq # electrical torque in pu te = mul( xmu, mul(dae.x[self.irq], dae.y[self.isd]) - mul(dae.x[self.ird], dae.y[self.isq])) for i in range(self.n): if te[i] < 0: logger.error( 'Pe < 0 on bus <{}>. Wind speed initialize failed.'.format( self.bus[i])) retval = False # wind power in pu pw = mul(te, omega) dae.y[self.pw] = pw # wind speed initialization loop R = 4 * pi * self.system.freq * mul(self.R, self.ngb, div( 1, self.npole)) AA = pi * self.R**2 vw = 0.9 * self.Vwn for i in range(self.n): mis = 1 niter = 0 while abs(mis) > self.system.tds.config.tol: if niter > 50: logger.error( 'Wind <{}> init failed. ' 'Try increasing the nominal wind speed.'.format( self.wind[i])) retval = False break pw_iter, jac = self.windpower(self.ngen[i], self.rho[i], vw[i], AA[i], R[i], omega[i], theta[i]) mis = pw_iter - pw[i] inc = -mis / jac[1] vw[i] += inc niter += 1 # set wind speed dae.x[self.vw] = div(vw, self.Vwn) lamb = div(omega, vw, div(1, R)) ilamb = div(1, (div(1, lamb + 0.08 * theta) - div(0.035, theta**3 + 1))) cp = 0.22 * mul( div(116, ilamb) - 0.4 * theta - 5, exp(div(-12.5, ilamb))) dae.y[self.lamb] = lamb dae.y[self.ilamb] = ilamb dae.y[self.cp] = cp self.system.rmgen(self.gen) if not retval: logger.error('DFIG initialization failed') return retval
def init1(self, dae): self.servcall(dae) mva = self.system.mva self.p0 = mul(self.p0, 1) self.v120 = self.v12 self.toMb = div(mva, self.Sn) # to machine base self.toSb = self.Sn / mva # to system base rs = matrix(self.rs) xd = matrix(self.xd) xq = matrix(self.xq) psip = matrix(self.psip) Pg = matrix(self.p0) # rotor speed omega = 1 * (ageb(mva * Pg, self.Sn)) + \ mul(0.5 + 0.5 * mul(Pg, self.toMb), aandb(agtb(Pg, 0), altb(mva * Pg, self.Sn))) + \ 0.5 * (aleb(mva * Pg, 0)) theta = mul(self.Kp, mround(1000 * (omega - 1)) / 1000) theta = mmax(theta, 0) # variables to initialize iteratively: vsd, vsq, isd, isq vsd = matrix(0.8, (self.n, 1)) vsq = matrix(0.6, (self.n, 1)) isd = matrix(self.p0 / 2) isq = matrix(self.p0 / 2) for i in range(self.n): # vsd = 0.5 # vsq = self.psip[i] # isd = Pg / 2 # isq = Pg / 2 x = matrix([vsd[i], vsq[i], isd[i], isq[i]]) mis = ones(4, 1) jac = sparse(matrix(0, (4, 4), 'd')) iter = 0 while (max(abs(mis))) > self.system.tds.config.tol: if iter > 40: logger.error( 'Initialization of WTG4DC <{}> failed.'.format( self.name[i])) break mis[0] = x[0] * x[2] + x[1] * x[3] - Pg[i] # mis[1] = omega[i]*x[3] * (psip[i] + (xq[i] - xd[i]) * x[2])\ # - Pg[i] mis[1] = omega[i] * x[3] * (psip[i] - xd[i] * x[2]) - Pg[i] mis[2] = -x[0] - rs[i] * x[2] + omega[i] * xq[i] * x[3] mis[3] = x[1] + rs[i] * x[3] + omega[i] * xd[i] * x[2] - \ omega[i] * psip[i] jac[0, 0] = x[2] jac[0, 1] = x[3] jac[0, 2] = x[0] jac[0, 3] = x[1] jac[1, 2] = omega[i] * x[3] * (-xd[i]) jac[1, 3] = omega[i] * (psip[i] + (-xd[i]) * x[2]) jac[2, 0] = -1 jac[2, 2] = -rs[i] jac[2, 3] = omega[i] * xq[i] jac[3, 1] = 1 jac[3, 2] = omega[i] * xd[i] jac[3, 3] = rs[i] linsolve(jac, mis) x -= mis iter += 1 vsd[i] = x[0] vsq[i] = x[1] isd[i] = x[2] isq[i] = x[3] dae.y[self.isd] = isd dae.y[self.vsd] = vsd dae.y[self.vsq] = vsq dae.x[self.isq] = isq dae.x[self.omega_m] = mul(self.u0, omega) dae.x[self.theta_p] = mul(self.u0, theta) dae.y[self.pwa] = mmax(mmin(2 * dae.x[self.omega_m] - 1, 1), 0) self.ps0 = mul(vsd, isd) + mul(vsq, isq) self.qs0 = mul(vsq, isd) - mul(vsd, isq) self.te0 = mul(isq, psip + mul(xq - xd, isd)) dae.y[self.te] = self.te0 dae.y[self.ps] = self.ps0 MPPT.init1(self, dae) Turbine.init1(self, dae) self.system.rmgen(self.dcgen)
def state_matrix(system): """Return state matrix""" Gyx = matrix(system.DAE.Gx) linsolve(system.DAE.Gy, Gyx) return matrix(system.DAE.Fx - system.DAE.Fy*Gyx)