def runopf_w_res(*args): """Runs an optimal power flow with fixed zonal reserves. Runs an optimal power flow with the addition of reserve requirements specified as a set of fixed zonal reserves. See L{runopf} for a description of the input and output arguments, which are the same, with the exception that the case file or dict C{casedata} must define a 'reserves' field, which is a dict with the following fields: - C{zones} C{nrz x ng}, C{zone(i, j) = 1}, if gen C{j} belongs to zone C{i} 0, otherwise - C{req} C{nrz x 1}, zonal reserve requirement in MW - C{cost} (C{ng} or C{ngr}) C{x 1}, cost of reserves in $/MW - C{qty} (C{ng} or C{ngr}) C{x 1}, max quantity of reserves in MW (optional) where C{nrz} is the number of reserve zones and C{ngr} is the number of generators belonging to at least one reserve zone and C{ng} is the total number of generators. In addition to the normal OPF output, the C{results} dict contains a new 'reserves' field with the following fields, in addition to those provided in the input: - C{R} - C{ng x 1}, reserves provided by each gen in MW - C{Rmin} - C{ng x 1}, lower limit on reserves provided by each gen, (MW) - C{Rmax} - C{ng x 1}, upper limit on reserves provided by each gen, (MW) - C{mu.l} - C{ng x 1}, shadow price on reserve lower limit, ($/MW) - C{mu.u} - C{ng x 1}, shadow price on reserve upper limit, ($/MW) - C{mu.Pmax} - C{ng x 1}, shadow price on C{Pg + R <= Pmax} constraint, ($/MW) - C{prc} - C{ng x 1}, reserve price for each gen equal to maximum of the shadow prices on the zonal requirement constraint for each zone the generator belongs to See L{t.t_case30_userfcns} for an example case file with fixed reserves, and L{toggle_reserves} for the implementation. Calling syntax options:: results = runopf_w_res(casedata) results = runopf_w_res(casedata, ppopt) results = runopf_w_res(casedata, ppopt, fname) results = runopf_w_res(casedata, [popt, fname, solvedcase) results, success = runopf_w_res(...) Example:: results = runopf_w_res('t_case30_userfcns') @see: L{runopf}, L{toggle_reserves}, L{t.t_case30_userfcns} @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ppc = loadcase(args[0]) ppc = toggle_reserves(ppc, 'on') r = runopf(ppc, *args[1:]) r = toggle_reserves(r, 'off') return r
def optimal_power_flow_energy_reserve(*args): casedata = args[0] # Target power flow modelling beta = args[1] # The reserve level mpc = loadcase(casedata) # Import the power flow modelling ## convert to internal indexing mpc = ext2int(mpc) baseMVA, bus, gen, branch,gencost = mpc["baseMVA"], mpc["bus"], mpc["gen"], mpc["branch"],mpc["gencost"] # nb = shape(mpc['bus'])[0] ## number of buses nl = shape(mpc['branch'])[0] ## number of branches ng = shape(mpc['gen'])[0] ## number of dispatchable injections ## Formualte the stat = branch[:, BR_STATUS] ## ones at in-service branches b = stat / branch[:, BR_X] ## series susceptance tap = ones(nl) ## default tap ratio = 1 i = find(branch[:, TAP]) ## indices of non-zero tap ratios tap[i] = branch[i, TAP] ## assign non-zero tap ratios ## build connection matrix Cft = Cf - Ct for line and from - to buses f = branch[:, F_BUS] ## list of "from" buses t = branch[:, T_BUS] ## list of "to" buses i = r_[range(nl), range(nl)] ## double set of row indices ## connection matrix Cft = sparse((r_[ones(nl), -ones(nl)], (i, r_[f, t])), (nl, nb)) ## build Bf such that Bf * Va is the vector of real branch powers injected ## at each branch's "from" bus Bf = sparse((r_[b, -b], (i, r_[f, t])), shape=(nl, nb)) ## = spdiags(b, 0, nl, nl) * Cft ## build Bbus Bbus = Cft.T * Bf # The distribution factor Distribution_factor = sparse(Bf*inv(Bbus)) Cg = sparse((ones(ng), (gen[:, GEN_BUS], arange(ng))), (nb, ng)) # Sparse index generation method is different from the way of matlab Cd = sparse((ones(nb), (bus[:, BUS_I], arange(nb))), (nb, nb)) # Sparse index load Pd = sum(bus[:,PD]) # Total power demand # Formulate the problem lb = concatenate((gen[:,PMIN],zeros(ng))) # extend the ub = concatenate((gen[:,PMAX],gen[:,PMAX])) Aeq = sparse(concatenate((ones(ng),zeros(ng)))) beq = [Pd] Aineq = sparse(hstack([Distribution_factor * Cg,zeros((nl,ng))])) Aineq = vstack([Aineq, -Aineq]) # The ramp reserve requirement Aineq = vstack([Aineq, sparse((r_[ones(ng), ones(ng)], (r_[arange(ng), arange(ng)], r_[arange(ng), ng+arange(ng)])), (ng, 2*ng))]) Aineq = vstack([Aineq, sparse((r_[-ones(ng), ones(ng)], (r_[arange(ng), arange(ng)], r_[arange(ng), ng+arange(ng)])), (ng, 2*ng))]) bineq = concatenate((branch[:, RATE_A] + Distribution_factor * Cd * bus[:, PD], branch[:, RATE_A] - Distribution_factor * Cd * bus[:, PD])) bineq = concatenate((bineq, gen[:, PMAX])) bineq = concatenate((bineq, -gen[:, PMIN])) c = concatenate((gencost[:,5],zeros(ng))) Q = diag(concatenate((gencost[:,4],zeros(ng)))) (Pg,obj) = miqp_gurobi(c = c,Q = Q, Aeq = Aeq, beq = beq, A = Aineq, b = bineq, xmin = lb,xmax = ub) obj = obj + sum(gencost[:,6]) return Pg, obj
def t_makeLODF(quiet=False): """Tests for C{makeLODF}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ntests = 31 t_begin(ntests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_auction_case') verbose = 0 #not quiet ## load case ppc = loadcase(casefile) ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) r = rundcopf(ppc, ppopt) baseMVA, bus, gen, branch = r['baseMVA'], r['bus'], r['gen'], r['branch'] _, bus, gen, branch = ext2int1(bus, gen, branch) ## compute injections and flows F0 = branch[:, PF] ## create some PTDF matrices H = makePTDF(baseMVA, bus, branch, 0) ## create some PTDF matrices try: LODF = makeLODF(branch, H) except ZeroDivisionError: pass ## take out non-essential lines one-by-one and see what happens ppc['bus'] = bus ppc['gen'] = gen branch0 = branch outages = r_[arange(12), arange(13, 15), arange(16, 18), [19], arange(26, 33), arange(34, 41)] for k in outages: ppc['branch'] = branch0.copy() ppc['branch'][k, BR_STATUS] = 0 r, _ = rundcpf(ppc, ppopt) baseMVA, bus, gen, branch = \ r['baseMVA'], r['bus'], r['gen'], r['branch'] F = branch[:, PF] t_is(LODF[:, k], (F - F0) / F0[k], 6, 'LODF[:, %d]' % k) t_end()
def t_makeLODF(quiet=False): """Tests for C{makeLODF}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ntests = 31 t_begin(ntests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_auction_case') verbose = 0#not quiet ## load case ppc = loadcase(casefile) ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) r = rundcopf(ppc, ppopt) baseMVA, bus, gen, branch = r['baseMVA'], r['bus'], r['gen'], r['branch'] _, bus, gen, branch = ext2int1(bus, gen, branch) ## compute injections and flows F0 = branch[:, PF] ## create some PTDF matrices H = makePTDF(baseMVA, bus, branch, 0) ## create some PTDF matrices try: LODF = makeLODF(branch, H) except ZeroDivisionError: pass ## take out non-essential lines one-by-one and see what happens ppc['bus'] = bus ppc['gen'] = gen branch0 = branch outages = r_[arange(12), arange(13, 15), arange(16, 18), [19], arange(26, 33), arange(34, 41)] for k in outages: ppc['branch'] = branch0.copy() ppc['branch'][k, BR_STATUS] = 0 r, _ = rundcpf(ppc, ppopt) baseMVA, bus, gen, branch = \ r['baseMVA'], r['bus'], r['gen'], r['branch'] F = branch[:, PF] t_is(LODF[:, k], (F - F0) / F0[k], 6, 'LODF[:, %d]' % k) t_end()
def open_fn(self): """Function for the Open action.""" ########################### # TO DO - Confirmation for opening file if data is unsaved # - Put open filename in title bar ########################### fname = QtGui.QFileDialog.getOpenFileName(self, "Open Case File", "", "Case files (*.py *.mat)") if fname: try: gui_globals.ppc = loadcase(fname) self.refresh_data() gui_globals.filename = fname self.show_status_message("Case File " + fname + " successfully loaded.") self.log.write("Case File " + fname + " successfully loaded.\n") except: self.show_status_message("Failed to open " + fname + ".", error = True, beep = True) self.log.write("Failed to open " + fname + ".\n") else: self.show_status_message("Open Data File cancelled.")
def t_ext2int2ext(quiet=False): """Tests C{ext2int} and C{int2ext}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ t_begin(85, quiet) ##----- ppc = e2i_data/i2e_data(ppc) ----- t = 'ppc = e2i_data(ppc) : ' ppce = loadcase(t_case_ext()) ppci = loadcase(t_case_int()) ppc = e2i_data(ppce) t_is(ppc['bus'], ppci['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppci['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppci['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppci['gencost'], 12, [t, 'gencost']) t_is(ppc['areas'], ppci['areas'], 12, [t, 'areas']) t_is(ppc['A'], ppci['A'], 12, [t, 'A']) t_is(ppc['N'], ppci['N'], 12, [t, 'N']) t = 'ppc = e2i_data(ppc) - repeat : ' ppc = e2i_data(ppc) t_is(ppc['bus'], ppci['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppci['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppci['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppci['gencost'], 12, [t, 'gencost']) t_is(ppc['areas'], ppci['areas'], 12, [t, 'areas']) t_is(ppc['A'], ppci['A'], 12, [t, 'A']) t_is(ppc['N'], ppci['N'], 12, [t, 'N']) t = 'ppc = i2e_data(ppc) : ' ppc = i2e_data(ppc) t_is(ppc['bus'], ppce['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppce['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppce['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppce['gencost'], 12, [t, 'gencost']) t_is(ppc['areas'], ppce['areas'], 12, [t, 'areas']) t_is(ppc['A'], ppce['A'], 12, [t, 'A']) t_is(ppc['N'], ppce['N'], 12, [t, 'N']) ##----- val = e2i_data/i2e_data(ppc, val, ...) ----- t = 'val = e2i_data(ppc, val, \'bus\')' ppc = e2i_data(ppce) got = e2i_data(ppc, ppce['xbus'], 'bus') ex = ppce['xbus'] ex = delete(ex, 5, 0) t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, \'bus\')' tmp = ones(ppce['xbus'].shape) tmp[5, :] = ppce['xbus'][5, :] got = i2e_data(ppc, ex, tmp, 'bus') t_is(got, ppce['xbus'], 12, t) t = 'val = e2i_data(ppc, val, \'bus\', 1)' got = e2i_data(ppc, ppce['xbus'], 'bus', 1) ex = ppce['xbus'] ex = delete(ex, 5, 1) t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, \'bus\', 1)' tmp = ones(ppce['xbus'].shape) tmp[:, 5] = ppce['xbus'][:, 5] got = i2e_data(ppc, ex, tmp, 'bus', 1) t_is(got, ppce['xbus'], 12, t) t = 'val = e2i_data(ppc, val, \'gen\')' got = e2i_data(ppc, ppce['xgen'], 'gen') ex = ppce['xgen'][[3, 1, 0], :] t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, \'gen\')' tmp = ones(ppce['xgen'].shape) tmp[2, :] = ppce['xgen'][2, :] got = i2e_data(ppc, ex, tmp, 'gen') t_is(got, ppce['xgen'], 12, t) t = 'val = e2i_data(ppc, val, \'gen\', 1)' got = e2i_data(ppc, ppce['xgen'], 'gen', 1) ex = ppce['xgen'][:, [3, 1, 0]] t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, \'gen\', 1)' tmp = ones(ppce['xgen'].shape) tmp[:, 2] = ppce['xgen'][:, 2] got = i2e_data(ppc, ex, tmp, 'gen', 1) t_is(got, ppce['xgen'], 12, t) t = 'val = e2i_data(ppc, val, \'branch\')' got = e2i_data(ppc, ppce['xbranch'], 'branch') ex = ppce['xbranch'] ex = delete(ex, 6, 0) t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, \'branch\')' tmp = ones(ppce['xbranch'].shape) tmp[6, :] = ppce['xbranch'][6, :] got = i2e_data(ppc, ex, tmp, 'branch') t_is(got, ppce['xbranch'], 12, t) t = 'val = e2i_data(ppc, val, \'branch\', 1)' got = e2i_data(ppc, ppce['xbranch'], 'branch', 1) ex = ppce['xbranch'] ex = delete(ex, 6, 1) t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, \'branch\', 1)' tmp = ones(ppce['xbranch'].shape) tmp[:, 6] = ppce['xbranch'][:, 6] got = i2e_data(ppc, ex, tmp, 'branch', 1) t_is(got, ppce['xbranch'], 12, t) t = 'val = e2i_data(ppc, val, {\'branch\', \'gen\', \'bus\'})' got = e2i_data(ppc, ppce['xrows'], ['branch', 'gen', 'bus']) ex = r_[ppce['xbranch'][list(range(6)) + list(range(7, 10)), :4], ppce['xgen'][[3, 1, 0], :], ppce['xbus'][list(range(5)) + list(range(6, 10)), :4], -1 * ones((2, 4))] t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, {\'branch\', \'gen\', \'bus\'})' tmp1 = ones(ppce['xbranch'][:, :4].shape) tmp1[6, :4] = ppce['xbranch'][6, :4] tmp2 = ones(ppce['xgen'].shape) tmp2[2, :] = ppce['xgen'][2, :] tmp3 = ones(ppce['xbus'][:, :4].shape) tmp3[5, :4] = ppce['xbus'][5, :4] tmp = r_[tmp1, tmp2, tmp3] got = i2e_data(ppc, ex, tmp, ['branch', 'gen', 'bus']) t_is(got, ppce['xrows'], 12, t) t = 'val = e2i_data(ppc, val, {\'branch\', \'gen\', \'bus\'}, 1)' got = e2i_data(ppc, ppce['xcols'], ['branch', 'gen', 'bus'], 1) ex = r_[ppce['xbranch'][list(range(6)) + list(range(7, 10)), :4], ppce['xgen'][[3, 1, 0], :], ppce['xbus'][list(range(5)) + list(range(6, 10)), :4], -1 * ones((2, 4))].T t_is(got, ex, 12, t) t = 'val = i2e_data(ppc, val, oldval, {\'branch\', \'gen\', \'bus\'}, 1)' tmp1 = ones(ppce['xbranch'][:, :4].shape) tmp1[6, :4] = ppce['xbranch'][6, :4] tmp2 = ones(ppce['xgen'].shape) tmp2[2, :] = ppce['xgen'][2, :] tmp3 = ones(ppce['xbus'][:, :4].shape) tmp3[5, :4] = ppce['xbus'][5, :4] tmp = r_[tmp1, tmp2, tmp3].T got = i2e_data(ppc, ex, tmp, ['branch', 'gen', 'bus'], 1) t_is(got, ppce['xcols'], 12, t) ##----- ppc = e2i_field/i2e_field(ppc, field, ...) ----- t = 'ppc = e2i_field(ppc, field, \'bus\')' ppc = e2i_field(ppce) ex = ppce['xbus'] ex = delete(ex, 5, 0) got = e2i_field(ppc, 'xbus', 'bus') t_is(got['xbus'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, \'bus\')' got = i2e_field(got, 'xbus', ordering='bus') t_is(got['xbus'], ppce['xbus'], 12, t) t = 'ppc = e2i_field(ppc, field, \'bus\', 1)' ex = ppce['xbus'] ex = delete(ex, 5, 1) got = e2i_field(ppc, 'xbus', 'bus', 1) t_is(got['xbus'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, \'bus\', 1)' got = i2e_field(got, 'xbus', ordering='bus', dim=1) t_is(got['xbus'], ppce['xbus'], 12, t) t = 'ppc = e2i_field(ppc, field, \'gen\')' ex = ppce['xgen'][[3, 1, 0], :] got = e2i_field(ppc, 'xgen', 'gen') t_is(got['xgen'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, \'gen\')' got = i2e_field(got, 'xgen', ordering='gen') t_is(got['xgen'], ppce['xgen'], 12, t) t = 'ppc = e2i_field(ppc, field, \'gen\', 1)' ex = ppce['xgen'][:, [3, 1, 0]] got = e2i_field(ppc, 'xgen', 'gen', 1) t_is(got['xgen'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, \'gen\', 1)' got = i2e_field(got, 'xgen', ordering='gen', dim=1) t_is(got['xgen'], ppce['xgen'], 12, t) t = 'ppc = e2i_field(ppc, field, \'branch\')' ex = ppce['xbranch'] ex = delete(ex, 6, 0) got = e2i_field(ppc, 'xbranch', 'branch') t_is(got['xbranch'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, \'branch\')' got = i2e_field(got, 'xbranch', ordering='branch') t_is(got['xbranch'], ppce['xbranch'], 12, t) t = 'ppc = e2i_field(ppc, field, \'branch\', 1)' ex = ppce['xbranch'] ex = delete(ex, 6, 1) got = e2i_field(ppc, 'xbranch', 'branch', 1) t_is(got['xbranch'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, \'branch\', 1)' got = i2e_field(got, 'xbranch', ordering='branch', dim=1) t_is(got['xbranch'], ppce['xbranch'], 12, t) t = 'ppc = e2i_field(ppc, field, {\'branch\', \'gen\', \'bus\'})' ex = r_[ppce['xbranch'][list(range(6)) + list(range(7, 10)), :4], ppce['xgen'][[3, 1, 0], :], ppce['xbus'][list(range(5)) + list(range(6, 10)), :4], -1 * ones((2, 4))] got = e2i_field(ppc, 'xrows', ['branch', 'gen', 'bus']) t_is(got['xrows'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, {\'branch\', \'gen\', \'bus\'})' got = i2e_field(got, 'xrows', ordering=['branch', 'gen', 'bus']) t_is(got['xrows'], ppce['xrows'], 12, t) t = 'ppc = e2i_field(ppc, field, {\'branch\', \'gen\', \'bus\'}, 1)' ex = r_[ppce['xbranch'][list(range(6)) + list(range(7, 10)), :4], ppce['xgen'][[3, 1, 0], :], ppce['xbus'][list(range(5)) + list(range(6, 10)), :4], -1 * ones((2, 4))].T got = e2i_field(ppc, 'xcols', ['branch', 'gen', 'bus'], 1) t_is(got['xcols'], ex, 12, t) t = 'ppc = i2e_field(ppc, field, {\'branch\', \'gen\', \'bus\'})' got = i2e_field(got, 'xcols', ordering=['branch', 'gen', 'bus'], dim=1) t_is(got['xcols'], ppce['xcols'], 12, t) t = 'ppc = e2i_field(ppc, {\'field1\', \'field2\'}, ordering)' ex = ppce['x']['more'][[3, 1, 0], :] got = e2i_field(ppc, ['x', 'more'], 'gen') t_is(got['x']['more'], ex, 12, t) t = 'ppc = i2e_field(ppc, {\'field1\', \'field2\'}, ordering)' got = i2e_field(got, ['x', 'more'], ordering='gen') t_is(got['x']['more'], ppce['x']['more'], 12, t) t = 'ppc = e2i_field(ppc, {\'field1\', \'field2\'}, ordering, 1)' ex = ppce['x']['more'][:, [3, 1, 0]] got = e2i_field(ppc, ['x', 'more'], 'gen', 1) t_is(got['x']['more'], ex, 12, t) t = 'ppc = i2e_field(ppc, {\'field1\', \'field2\'}, ordering, 1)' got = i2e_field(got, ['x', 'more'], ordering='gen', dim=1) t_is(got['x']['more'], ppce['x']['more'], 12, t) ##----- more ppc = ext2int/int2ext(ppc) ----- t = 'ppc = ext2int(ppc) - bus/gen/branch only : ' ppce = loadcase(t_case_ext()) ppci = loadcase(t_case_int()) del ppce['gencost'] del ppce['areas'] del ppce['A'] del ppce['N'] del ppci['gencost'] del ppci['areas'] del ppci['A'] del ppci['N'] ppc = ext2int(ppce) t_is(ppc['bus'], ppci['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppci['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppci['gen'], 12, [t, 'gen']) t = 'ppc = ext2int(ppc) - no areas/A : ' ppce = loadcase(t_case_ext()) ppci = loadcase(t_case_int()) del ppce['areas'] del ppce['A'] del ppci['areas'] del ppci['A'] ppc = ext2int(ppce) t_is(ppc['bus'], ppci['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppci['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppci['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppci['gencost'], 12, [t, 'gencost']) t_is(ppc['N'], ppci['N'], 12, [t, 'N']) t = 'ppc = ext2int(ppc) - Qg cost, no N : ' ppce = loadcase(t_case_ext()) ppci = loadcase(t_case_int()) del ppce['N'] del ppci['N'] ppce['gencost'] = c_[ppce['gencost'], ppce['gencost']] ppci['gencost'] = c_[ppci['gencost'], ppci['gencost']] ppc = ext2int(ppce) t_is(ppc['bus'], ppci['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppci['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppci['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppci['gencost'], 12, [t, 'gencost']) t_is(ppc['areas'], ppci['areas'], 12, [t, 'areas']) t_is(ppc['A'], ppci['A'], 12, [t, 'A']) t = 'ppc = ext2int(ppc) - A, N are DC sized : ' ppce = loadcase(t_case_ext()) ppci = loadcase(t_case_int()) eVmQgcols = list(range(10, 20)) + list(range(24, 28)) iVmQgcols = list(range(9, 18)) + list(range(21, 24)) ppce['A'] = delete(ppce['A'], eVmQgcols, 1) ppce['N'] = delete(ppce['N'], eVmQgcols, 1) ppci['A'] = delete(ppci['A'], iVmQgcols, 1) ppci['N'] = delete(ppci['N'], iVmQgcols, 1) ppc = ext2int(ppce) t_is(ppc['bus'], ppci['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppci['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppci['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppci['gencost'], 12, [t, 'gencost']) t_is(ppc['areas'], ppci['areas'], 12, [t, 'areas']) t_is(ppc['A'], ppci['A'], 12, [t, 'A']) t_is(ppc['N'], ppci['N'], 12, [t, 'N']) t = 'ppc = int2ext(ppc) - A, N are DC sized : ' ppc = int2ext(ppc) t_is(ppc['bus'], ppce['bus'], 12, [t, 'bus']) t_is(ppc['branch'], ppce['branch'], 12, [t, 'branch']) t_is(ppc['gen'], ppce['gen'], 12, [t, 'gen']) t_is(ppc['gencost'], ppce['gencost'], 12, [t, 'gencost']) t_is(ppc['areas'], ppce['areas'], 12, [t, 'areas']) t_is(ppc['A'], ppce['A'], 12, [t, 'A']) t_is(ppc['N'], ppce['N'], 12, [t, 'N']) t_end()
def t_opf_ipopt(quiet=False): """Tests for IPOPT-based AC optimal power flow. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ num_tests = 101 t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') verbose = 0#not quiet t0 = 'IPOPT : ' ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=580) ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## get solved AC power flow case from MAT-file soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf['bus_soln'] gen_soln = soln9_opf['gen_soln'] branch_soln = soln9_opf['branch_soln'] f_soln = soln9_opf['f_soln'][0] ## run OPF t = t0 r = runopf(casefile, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ## run with automatic conversion of single-block pwl to linear costs t = ''.join([t0, '(single-block PWL) : ']) ppc = loadcase(casefile) ppc['gencost'][2, NCOST] = 2 r = runopf(ppc, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) xr = r_[r['var']['val']['Va'], r['var']['val']['Vm'], r['var']['val']['Pg'], r['var']['val']['Qg'], 0, r['var']['val']['y']] t_is(r['x'], xr, 8, [t, 'check on raw x returned from OPF']) ## get solved AC power flow case from MAT-file soln9_opf_Plim = loadmat(join(tdir, 'soln9_opf_Plim.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_Plim['bus_soln'] gen_soln = soln9_opf_Plim['gen_soln'] branch_soln = soln9_opf_Plim['branch_soln'] f_soln = soln9_opf_Plim['f_soln'][0] ## run OPF with active power line limits t = ''.join([t0, '(P line lim) : ']) ppopt1 = ppoption(ppopt, OPF_FLOW_LIM=1) r = runopf(casefile, ppopt1) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ##----- test OPF with quadratic gen costs moved to generalized costs ----- ppc = loadcase(casefile) ppc['gencost'] = array([ [2, 1500, 0, 3, 0.11, 5, 0], [2, 2000, 0, 3, 0.085, 1.2, 0], [2, 3000, 0, 3, 0.1225, 1, 0] ]) r = runopf(ppc, ppopt) bus_soln, gen_soln, branch_soln, f_soln, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] branch_soln = branch_soln[:, :MU_ST + 1] A = None l = array([]) u = array([]) nb = ppc['bus'].shape[0] # number of buses ng = ppc['gen'].shape[0] # number of gens thbas = 0; thend = thbas + nb vbas = thend; vend = vbas + nb pgbas = vend; pgend = pgbas + ng # qgbas = pgend; qgend = qgbas + ng nxyz = 2 * nb + 2 * ng N = sparse((ppc['baseMVA'] * ones(ng), (arange(ng), arange(pgbas, pgend))), (ng, nxyz)) fparm = ones((ng, 1)) * array([[1, 0, 0, 1]]) ix = argsort(ppc['gen'][:, 0]) H = 2 * spdiags(ppc['gencost'][ix, 4], 0, ng, ng, 'csr') Cw = ppc['gencost'][ix, 5] ppc['gencost'][:, 4:7] = 0 ## run OPF with quadratic gen costs moved to generalized costs t = ''.join([t0, 'w/quadratic generalized gen cost : ']) r = opf(ppc, A, l, u, ppopt, N, fparm, H, Cw) f, bus, gen, branch, success = \ r['f'], r['bus'], r['gen'], r['branch'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_is(r['cost']['usr'], f, 12, [t, 'user cost']) ##----- run OPF with extra linear user constraints & costs ----- ## single new z variable constrained to be greater than or equal to ## deviation from 1 pu voltage at bus 1, linear cost on this z ## get solved AC power flow case from MAT-file soln9_opf_extras1 = loadmat(join(tdir, 'soln9_opf_extras1.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_extras1['bus_soln'] gen_soln = soln9_opf_extras1['gen_soln'] branch_soln = soln9_opf_extras1['branch_soln'] f_soln = soln9_opf_extras1['f_soln'][0] row = [0, 0, 1, 1] col = [9, 24, 9, 24] A = sparse(([-1, 1, 1, 1], (row, col)), (2, 25)) u = array([Inf, Inf]) l = array([-1, 1]) N = sparse(([1], ([0], [24])), (1, 25)) ## new z variable only fparm = array([[1, 0, 0, 1]]) ## w = r = z H = sparse((1, 1)) ## no quadratic term Cw = array([100.0]) t = ''.join([t0, 'w/extra constraints & costs 1 : ']) r = opf(casefile, A, l, u, ppopt, N, fparm, H, Cw) f, bus, gen, branch, success = \ r['f'], r['bus'], r['gen'], r['branch'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_is(r['var']['val']['z'], 0.025419, 6, [t, 'user variable']) t_is(r['cost']['usr'], 2.5419, 4, [t, 'user cost']) ##----- test OPF with capability curves ----- ppc = loadcase(join(tdir, 't_case9_opfv2')) ## remove angle diff limits ppc['branch'][0, ANGMAX] = 360 ppc['branch'][8, ANGMIN] = -360 ## get solved AC power flow case from MAT-file soln9_opf_PQcap = loadmat(join(tdir, 'soln9_opf_PQcap.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_PQcap['bus_soln'] gen_soln = soln9_opf_PQcap['gen_soln'] branch_soln = soln9_opf_PQcap['branch_soln'] f_soln = soln9_opf_PQcap['f_soln'][0] ## run OPF with capability curves t = ''.join([t0, 'w/capability curves : ']) r = runopf(ppc, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ##----- test OPF with angle difference limits ----- ppc = loadcase(join(tdir, 't_case9_opfv2')) ## remove capability curves ppc['gen'][ix_(arange(1, 3), [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX])] = zeros((2, 6)) ## get solved AC power flow case from MAT-file soln9_opf_ang = loadmat(join(tdir, 'soln9_opf_ang.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_ang['bus_soln'] gen_soln = soln9_opf_ang['gen_soln'] branch_soln = soln9_opf_ang['branch_soln'] f_soln = soln9_opf_ang['f_soln'][0] ## run OPF with angle difference limits t = ''.join([t0, 'w/angle difference limits : ']) r = runopf(ppc, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 1, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_is(branch[:, ibr_angmu ], branch_soln[:, ibr_angmu ], 2, [t, 'branch angle mu']) ##----- test OPF with ignored angle difference limits ----- ## get solved AC power flow case from MAT-file soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf['bus_soln'] gen_soln = soln9_opf['gen_soln'] branch_soln = soln9_opf['branch_soln'] f_soln = soln9_opf['f_soln'][0] ## run OPF with ignored angle difference limits t = ''.join([t0, 'w/ignored angle difference limits : ']) ppopt1 = ppoption(ppopt, OPF_IGNORE_ANG_LIM=1) r = runopf(ppc, ppopt1) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] ## ang limits are not in this solution data, so let's remove them branch[0, ANGMAX] = 360 branch[8, ANGMIN] = -360 t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_end()
def runcpf(basecasedata=None, targetcasedata=None, ppopt=None, fname='', solvedcase=''): # default arguments if basecasedata is None: basecasedata = join(dirname(__file__), 'case9') if targetcasedata is None: targetcasedata = join(dirname(__file__), 'case9target') ppopt = ppoption(ppopt) # options verbose = ppopt["VERBOSE"] step = ppopt["CPF_STEP"] parameterization = ppopt["CPF_PARAMETERIZATION"] adapt_step = ppopt["CPF_ADAPT_STEP"] cb_args = ppopt["CPF_USER_CALLBACK_ARGS"] # set up callbacks callback_names = ["cpf_default_callback"] if len(ppopt["CPF_USER_CALLBACK"]) > 0: if isinstance(ppopt["CPF_USER_CALLBACK"], list): callback_names = r_[callback_names, ppopt["CPF_USER_CALLBACK"]] else: callback_names.append(ppopt["CPF_USER_CALLBACK"]) callbacks = [] for callback_name in callback_names: callbacks.append(getattr(cpf_callbacks, callback_name)) # read base case data ppcbase = loadcase(basecasedata) nb = ppcbase["bus"].shape[0] # add zero columns to branch for flows if needed if ppcbase["branch"].shape[1] < QT: ppcbase["branch"] = c_[ppcbase["branch"], zeros((ppcbase["branch"].shape[0], QT - ppcbase["branch"].shape[1] + 1))] # convert to internal indexing ppcbase = ext2int(ppcbase) baseMVAb, busb, genb, branchb = \ ppcbase["baseMVA"], ppcbase["bus"], ppcbase["gen"], ppcbase["branch"] # get bus index lists of each type of bus ref, pv, pq = bustypes(busb, genb) # generator info onb = find(genb[:, GEN_STATUS] > 0) # which generators are on? gbusb = genb[onb, GEN_BUS].astype(int) # what buses are they at? # read target case data ppctarget = loadcase(targetcasedata) # add zero columns to branch for flows if needed if ppctarget["branch"].shape[1] < QT: ppctarget["branch"] = c_[ppctarget["branch"], zeros( (ppctarget["branch"].shape[0], QT - ppctarget["branch"].shape[1] + 1))] # convert to internal indexing ppctarget = ext2int(ppctarget) baseMVAt, bust, gent, brancht = \ ppctarget["baseMVA"], ppctarget["bus"], ppctarget["gen"], ppctarget["branch"] # get bus index lists of each type of bus # ref, pv, pq = bustypes(bust, gent) # generator info ont = find(gent[:, GEN_STATUS] > 0) # which generators are on? gbust = gent[ont, GEN_BUS].astype(int) # what buses are they at? # ----- run the power flow ----- t0 = time() if verbose > 0: v = ppver('all') stdout.write('PYPOWER Version %s, %s' % (v["Version"], v["Date"])) stdout.write(' -- AC Continuation Power Flow\n') # initial state # V0 = ones(bus.shape[0]) ## flat start V0 = busb[:, VM] * exp(1j * pi / 180 * busb[:, VA]) vcb = ones(V0.shape) # create mask of voltage-controlled buses vcb[pq] = 0 # exclude PQ buses k = find(vcb[gbusb]) # in-service gens at v-c buses V0[gbusb[k]] = genb[onb[k], VG] / abs(V0[gbusb[k]]) * V0[gbusb[k]] # build admittance matrices Ybus, Yf, Yt = makeYbus(baseMVAb, busb, branchb) # compute base case complex bus power injections (generation - load) Sbusb = makeSbus(baseMVAb, busb, genb) # compute target case complex bus power injections (generation - load) Sbust = makeSbus(baseMVAt, bust, gent) # scheduled transfer Sxfr = Sbust - Sbusb # Run the base case power flow solution if verbose > 2: ppopt_pf = ppoption(ppopt, VERBOSE=max(0, verbose - 1)) else: ppopt_pf = ppoption(ppopt, VERBOSE=max(0, verbose - 2)) lam = 0 V, success, iterations = newtonpf(Ybus, Sbusb, V0, ref, pv, pq, ppopt_pf) if verbose > 2: print('step %3d : lambda = %6.3f\n' % (0, 0)) elif verbose > 1: print('step %3d : lambda = %6.3f, %2d Newton steps\n', (0, 0, iterations)) lamprv = lam # lam at previous step Vprv = V # V at previous step continuation = 1 cont_steps = 0 # input args for callbacks cb_data = { "ppc_base": ppcbase, "ppc_target": ppctarget, "Sxfr": Sxfr, "Ybus": Ybus, "Yf": Yf, "Yt": Yt, "ref": ref, "pv": pv, "pq": pq, "ppopt": ppopt } cb_state = {} # invoke callbacks for k in range(len(callbacks)): cb_state, _ = callbacks[k](cont_steps, V, lam, V, lam, cb_data, cb_state, cb_args) if linalg.norm(Sxfr) == 0: if verbose: print( 'base case and target case have identical load and generation\n' ) continuation = 0 V0 = V lam0 = lam # tangent predictor z = [dx;dlam] z = zeros(2 * len(V) + 1) z[-1] = 1.0 while continuation: cont_steps = cont_steps + 1 # prediction for next step V0, lam0, z = cpf_predictor(V, lam, Ybus, Sxfr, pv, pq, step, z, Vprv, lamprv, parameterization) # save previous voltage, lambda before updating Vprv = V lamprv = lam # correction V, success, i, lam = cpf_corrector(Ybus, Sbusb, V0, ref, pv, pq, lam0, Sxfr, Vprv, lamprv, z, step, parameterization, ppopt_pf) if not success: continuation = 0 if verbose: print( 'step %3d : lambda = %6.3f, corrector did not converge in %d iterations\n' % (cont_steps, lam, i)) break if verbose > 2: print('step %3d : lambda = %6.3f\n' % (cont_steps, lam)) elif verbose > 1: print('step %3d : lambda = %6.3f, %2d corrector Newton steps\n' % (cont_steps, lam, i)) # invoke callbacks for k in range(len(callbacks)): cb_state, _ = callbacks[k](cont_steps, V, lam, V0, lam0, cb_data, cb_state, cb_args) if isinstance(ppopt["CPF_STOP_AT"], str): if ppopt["CPF_STOP_AT"].upper() == "FULL": if abs(lam) < 1e-8: # traced the full continuation curve if verbose: print( '\nTraced full continuation curve in %d continuation steps\n' % cont_steps) continuation = 0 elif lam < lamprv and lam - step < 0: # next step will overshoot step = lam # modify step-size parameterization = 1 # change to natural parameterization adapt_step = False # disable step-adaptivity else: # == 'NOSE' if lam < lamprv: # reached the nose point if verbose: print( '\nReached steady state loading limit in %d continuation steps\n' % cont_steps) continuation = 0 else: if lam < lamprv: if verbose: print( '\nReached steady state loading limit in %d continuation steps\n' % cont_steps) continuation = 0 elif abs(ppopt["CPF_STOP_AT"] - lam) < 1e-8: # reached desired lambda if verbose: print( '\nReached desired lambda %3.2f in %d continuation steps\n' % (ppopt["CPF_STOP_AT"], cont_steps)) continuation = 0 # will reach desired lambda in next step elif lam + step > ppopt["CPF_STOP_AT"]: step = ppopt["CPF_STOP_AT"] - lam # modify step-size parameterization = 1 # change to natural parameterization adapt_step = False # disable step-adaptivity if adapt_step and continuation: pvpq = r_[pv, pq] # Adapt stepsize cpf_error = linalg.norm( r_[angle(V[pq]), abs(V[pvpq]), lam] - r_[angle(V0[pq]), abs(V0[pvpq]), lam0], inf) if cpf_error < ppopt["CPF_ERROR_TOL"]: # Increase stepsize step = step * ppopt["CPF_ERROR_TOL"] / cpf_error if step > ppopt["CPF_STEP_MAX"]: step = ppopt["CPF_STEP_MAX"] else: # decrese stepsize step = step * ppopt["CPF_ERROR_TOL"] / cpf_error if step < ppopt["CPF_STEP_MIN"]: step = ppopt["CPF_STEP_MIN"] # invoke callbacks if success: cpf_results = {} for k in range(len(callbacks)): cb_state, cpf_results = callbacks[k](cont_steps, V, lam, V0, lam0, cb_data, cb_state, cb_args, results=cpf_results, is_final=True) else: cpf_results["iterations"] = i # update bus and gen matrices to reflect the loading and generation # at the noise point bust[:, PD] = busb[:, PD] + lam * (bust[:, PD] - busb[:, PD]) bust[:, QD] = busb[:, QD] + lam * (bust[:, QD] - busb[:, QD]) gent[:, PG] = genb[:, PG] + lam * (gent[:, PG] - genb[:, PG]) # update data matrices with solution bust, gent, brancht = pfsoln(baseMVAt, bust, gent, brancht, Ybus, Yf, Yt, V, ref, pv, pq) ppctarget["et"] = time() - t0 ppctarget["success"] = success # ----- output results ----- # convert back to original bus numbering & print results ppctarget["bus"], ppctarget["gen"], ppctarget[ "branch"] = bust, gent, brancht if success: n = cpf_results["iterations"] + 1 cpf_results["V_p"] = i2e_data(ppctarget, cpf_results["V_p"], full((nb, n), nan), "bus", 0) cpf_results["V_c"] = i2e_data(ppctarget, cpf_results["V_c"], full((nb, n), nan), "bus", 0) results = int2ext(ppctarget) results["cpf"] = cpf_results # zero out result fields of out-of-service gens & branches if len(results["order"]["gen"]["status"]["off"]) > 0: results["gen"][ix_(results["order"]["gen"]["status"]["off"], [PG, QG])] = 0 if len(results["order"]["branch"]["status"]["off"]) > 0: results["branch"][ix_(results["order"]["branch"]["status"]["off"], [PF, QF, PT, QT])] = 0 if fname: fd = None try: fd = open(fname, "a") except Exception as detail: stderr.write("Error opening %s: %s.\n" % (fname, detail)) finally: if fd is not None: printpf(results, fd, ppopt) fd.close() else: printpf(results, stdout, ppopt) # save solved case if solvedcase: savecase(solvedcase, results) return results, success
def FlujosAC(self, Sbase, t_index): for PVAC in self.PVAC: # Actualizar matriz de generación con valores interpolados self.genMatrix[PVAC.indice - 1, 1] = PVAC.P[t_index] / (Sbase * 1000000) self.genMatrix[PVAC.indice - 1, 2] = PVAC.Q[t_index] / (Sbase * 1000000) self.busMatrix = numpy.array([]) self.branchMatrix = numpy.array([]) for bus in self.Terminales: bus.actualizar(t_index, Sbase) self.busMatrix = numpy.concatenate((self.busMatrix, [ bus.ID, bus.Tipo, bus.P, bus.Q, 0, 0, 1, 1, 0, bus.Vnom, 1, 1.1, 0.9 ]), 0) i = 0 for branch in self.Branch: self.branchMatrix = numpy.concatenate((self.branchMatrix, [ branch.Term1.ID, branch.Term2.ID, branch.R, branch.X, branch.Y, branch.Snom, branch.Snom, branch.Snom, branch.Turns, 0, 1, -360, 360 ]), 0) branch.branchindex = i i = i + 1 # Crear caso para cargalo usando PYPOWER y correr flujos AC RedACdict = dict() RedACdict['baseMVA'] = Sbase RedACdict['bus'] = self.busMatrix.reshape((len(self.Terminales), 13)) RedACdict['branch'] = self.branchMatrix.reshape((len(self.Branch), 13)) RedACdict['gen'] = self.genMatrix.reshape((len(self.PVAC) + 1, 21)) # Cargar caso de pypower con matrices actualizadas caseRedAC = loadcase.loadcase(RedACdict) # Correr flujo de potencia con PYPOWER self.ACresults = runpf.runpf(caseRedAC) fecha = datetime.strftime(self.fechas[t_index], '%Y-%m-%d %H:%M:%S') # Guardar resultados de flujos para terminales for bus in self.Terminales: # Recuperar índice de bus en matriz de buses de pypower con resultados busindex = numpy.where( self.ACresults[0]['bus'][:, 0] == bus.ID)[0].item() # Guardar resultados respectivos bus.Results[fecha] = { 'V': self.ACresults[0]['bus'][busindex, 7].item(), 'delta': self.ACresults[0]['bus'][busindex, 8].item(), 'P': self.ACresults[0]['bus'][busindex, 2].item(), 'Q': self.ACresults[0]['bus'][busindex, 3].item() } # Guardar resultados de flujos para líneas y trafos for branch in self.Branch: # Recuperar potencias de entrada y salida de la rama Pf = self.ACresults[0]['branch'][branch.branchindex, 13].item() Qf = self.ACresults[0]['branch'][branch.branchindex, 14].item() Pt = self.ACresults[0]['branch'][branch.branchindex, 15].item() Qt = self.ACresults[0]['branch'][branch.branchindex, 16].item() # Calcular pérdidas y cargabilidad de cada rama Ploss = math.fabs(Pf - Pt) Qloss = math.fabs(Qf - Qt) Loading = math.sqrt(math.pow(Pf, 2) + math.pow(Qf, 2)) * 100 / branch.Snom # Guardar resultados respectivos branch.Results[fecha] = { 'Pf': Pf, 'Qf': Qf, 'Ploss': Ploss, 'Qloss': Qloss, 'Loading': Loading } self.CDC.Results[fecha] = { 'P': self.ACresults[0]['gen'][0, 1].item(), 'Q': self.ACresults[0]['gen'][0, 2].item() }
from pypower.loadcase import loadcase import matplotlib.pyplot as plt import numpy as np if __name__ == '__main__': ######### # SETUP # ######### print('----------------------------') print('PYPOWER-Dynamics - SMIB Test') print('----------------------------') # Load PYPOWER case ppc = loadcase('smib_case.py') # Program options dynopt = {} dynopt['h'] = 0.01 # step length (s) dynopt['t_sim'] = 15 # simulation time (s) dynopt[ 'max_err'] = 0.0001 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 50 # Nominal system frequency (Hz) # Integrator option #dynopt['iopt'] = 'mod_euler' dynopt['iopt'] = 'runge_kutta'
def t_total_load(quiet=False): """Tests for code in C{total_load}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ n_tests = 48 t_begin(n_tests, quiet) ppc = loadcase(join(dirname(__file__), 't_auction_case')) ppc['gen'][7, GEN_BUS] = 2 ## multiple d. loads per area, same bus as gen ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3]) ## put it load before gen in matrix ppc['gen'] = vstack([ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]]) ld = find(isload(ppc['gen'])) a = [None] * 3 lda = [None] * 3 for k in range(3): a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1) ## buses in area k tmp = find( in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k]) ) lda[k] = ld[tmp] ## disp loads in area k area = [None] * 3 for k in range(3): area[k] = {'fixed': {}, 'disp': {}, 'both': {}} area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD]) area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD]) area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN]) area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN]) area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX]) area[k]['disp']['q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax'] area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p'] area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q'] total = {'fixed': {}, 'disp': {}, 'both': {}} total['fixed']['p'] = sum(ppc['bus'][:, PD]) total['fixed']['q'] = sum(ppc['bus'][:, QD]) total['disp']['p'] = -sum(ppc['gen'][ld, PMIN]) total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN]) total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX]) total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax'] total['both']['p'] = total['fixed']['p'] + total['disp']['p'] total['both']['q'] = total['fixed']['q'] + total['disp']['q'] ##----- all load ----- t = 'Pd, _ = total_load(bus) : ' Pd, _ = total_load(ppc['bus']) t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus) : ' Pd, Qd = total_load(ppc['bus']) t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen) : ' Pd, _ = total_load(ppc['bus'], ppc['gen']) t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen) : ' Pd, Qd = total_load(ppc['bus'], ppc['gen']) t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, None, \'all\') : ' Pd, _ = total_load(ppc['bus'], None, 'all') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, None, \'all\') : ' Pd, Qd = total_load(ppc['bus'], None, 'all') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t_is(Qd, total['fixed']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t_is(Qd, total['both']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\', \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\', \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t_is(Qd, total['both']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\', \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\', \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t_is(Qd, total['fixed']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE') t_is(Pd, total['disp']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE') t_is(Pd, total['disp']['p'], 12, [t, 'Pd']) t_is(Qd, total['disp']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, None, \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'BOTH') t_is(Pd, r_[area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, None, \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'BOTH') t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, None, \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'FIXED') t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, None, \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'FIXED') t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, None, \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE') t_is(Pd, [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, None, \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE') t_is(Pd, [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['disp']['q'], area[1]['disp']['q'], area[2]['disp']['q']], 12, [t, 'Qd']) ##----- explicit single load zone ----- nb = ppc['bus'].shape[0] load_zone = zeros(nb, int) k = find(ppc['bus'][:, BUS_AREA] == 2) ## area 2 load_zone[k] = 1 t = 'Pd, _ = total_load(bus, gen, load_zone1, \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd']) t_is(Qd, area[1]['both']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone1, \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd']) t_is(Qd, area[1]['fixed']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd']) t_is(Qd, area[1]['disp']['q'], 12, [t, 'Qd']) ##----- explicit multiple load zone ----- load_zone = zeros(nb, int) k = find(ppc['bus'][:, BUS_AREA] == 3) ## area 3 load_zone[k] = 1 k = find(ppc['bus'][:, BUS_AREA] == 1) ## area 1 load_zone[k] = 2 t = 'Pd, _ = total_load(bus, gen, load_zone2, \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd']) t_is(Qd, [area[2]['both']['q'], area[0]['both']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone2, \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd']) t_is(Qd, [area[2]['fixed']['q'], area[0]['fixed']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd']) t_is(Qd, [area[2]['disp']['q'], area[0]['disp']['q']], 12, [t, 'Qd']) t_end()
def runacdcpf(caseac=None, casedc=None, pacdcopt=None, ppopt=None): """ Runs a sequential AC/DC power flow, optionally returning the results, a convergence flag and the time. Inputs (optional): CASEAC : ac power flow data either a PYPOWER case struct or a string containing the name of the file with the data (default ac case is 'case5_stagg', only used when both ac and dc power flow data are not defined) (see also CASEFORMAT and LOADCASE and PYPOWER) CASEDC : dc power flow data either a PYACDCPF case struct or a string containing the name of the file with the data (default dc case is 'case5_stagg_MTDCslack') (see also LOADCASEDC) PACDCOPT : PYACDCPF options vector to override default ac/dc power flow options. Can be used to specify tolerances, inclusion of limits, plot options and more (see also MACDCOPTION). PPOPT : PYPOWER options vector to override default options can be used to specify the solution algorithm, output options termination tolerances, and more (see also MPOPTION). Outputs: RESULTSAC : results struct, with the following fields from the input PYPOWER case: baseMVA, bus, branch, gen (but with solved voltages, power flows, etc.) RESULTSDC : results struct, with the following fields: input PYACDCPF dc case: baseMVAac, baseMVAdc, pol, busdc, convdc, branchdc (but with solved voltages, power flows, etc.) CONVERGED : converge flag, can additionally be returned TIMECALC : elapsed time, can additionally be returned Examples of usage: [resultsac, resultsdc, converged, te] = runacdcpf('case5_stagg', \ 'case5_stagg_MTDCdroop'); @author:Jef Beerten (KU Leuven) @author:Roni Irnawan (Aalborg University) """ ## start of time calculation t0 = time() ## add subdirectories to path if caseac is None: dirac = join(dirname(__file__), 'Cases', 'PowerflowAC') caseac = join(dirac, 'case5_stagg') # caseac = join(dirac, 'case3_inf') # caseac = join(dirac, 'case24_ieee_rts1996_3zones') # caseac = join(dirac, 'case24_ieee_rts1996_3zones_inf') if casedc is None: dirdc = join(dirname(__file__), 'Cases', 'PowerflowDC') # casedc = join(dirdc, 'case5_stagg_HVDCptp') # casedc = join(dirdc, 'case5_stagg_MTDCslack') casedc = join(dirdc, 'case5_stagg_MTDCdroop') # casedc = join(dirdc, 'case24_ieee_rts1996_MTDC') ## default arguments ppopt = ppoption(ppopt) ppopt["VERBOSE"] = 0 ppopt["OUT_ALL"] = 0 pacdcopt = pacdcoption(pacdcopt) ## options tolacdc = pacdcopt["TOLACDC"] itmaxacdc = pacdcopt["ITMAXACDC"] toldc = pacdcopt["TOLDC"] itmaxdc = pacdcopt["ITMAXDC"] tolslackdroop = pacdcopt["TOLSLACKDROOP"] itmaxslackdroop = pacdcopt["ITMAXSLACKDROOP"] tolslackdroopint = pacdcopt["TOLSLACKDROOPINT"] itmaxslackdroopint = pacdcopt["ITMAXSLACKDROOPINT"] multslack = pacdcopt["MULTSLACK"] limac = pacdcopt["LIMAC"] limdc = pacdcopt["LIMDC"] tollim = pacdcopt["TOLLIM"] output = pacdcopt["OUTPUT"] convplotopt = pacdcopt["CONVPLOTOPT"] ## ----- initialise ----- ## read data pdc = loadcasedc(casedc) ppc = loadcase(caseac) ##----- Data preparation ----- ## converter outage are considered as stations without ac grid connection pdc, conv0busi, conv1, conv1i, conv0, conv0i = convout(pdc) pdc['convdc'] = conv1 # only use converters without outage ## dc branch outages (remove branches from input data) brchdc1, brchdc1i, brchdc0, brchdc0i = brchdcout(pdc) pdc['branchdc'] = brchdc1 # only include branches in operation ## ac branch outages (remove branches from input data) brch1, brch1i, brch0, brch0i = brchout(ppc) ppc['branch'] = brch1 # only include branches in operation ## generator outages (remove non-operational generators from input data) gon = where(ppc['gen'][:,GEN_STATUS] > 0)[0] # which gens are on? goff = where(ppc['gen'][:,GEN_STATUS] == 0)[0] # which gens are off? gen0 = ppc['gen'][goff,:] # non-operational gens data ppc['gen'] = ppc['gen'][gon,:] #keep operational generators" ##----- External to internal numbering ----- ## dc network external to internal bus numbering i2edcpmt, i2edc, pdc = ext2intdc(pdc) ## ac network external to internal bus numbering acdmbus, i2eac, pdc, ppc = ext2intac(pdc,ppc) ## sort matrices by new bus numbers i2ebus = ppc['bus'][:,0].argsort() i2egen = ppc['gen'][:,0].argsort() i2ebrch = ppc['branch'][:,0].argsort() i2ebusdc = pdc['busdc'][:,0].argsort() i2econvdc = pdc['convdc'][:,0].argsort() i2ebrchdc = pdc['branchdc'][:,0].argsort() ppc['bus'] = ppc['bus'][i2ebus,:] ppc['gen'] = ppc['gen'][i2egen,:] ppc['branch'] = ppc['branch'][i2ebrch,:] pdc['busdc'] = pdc['busdc'][i2ebusdc,:] pdc['convdc'] = pdc['convdc'][i2econvdc,:] pdc['branchdc'] = pdc['branchdc'][i2ebrchdc,:] ## Per unit external to internal data conversion pdc = ext2intpu(ppc['baseMVA'],pdc) ##----- Additional data preparation & index initialisation ----- ## zero rows addition to convdc matrix (dc buses without converter) convdc1 = zeros((pdc['busdc'].shape[0]-pdc['convdc'].shape[0], pdc['convdc'].shape[1])) pdc['convdc'] = r_[pdc['convdc'],convdc1] ## indices initialisation bdci = where(pdc['busdc'][:,BUSAC_I])[0].astype(int) cdci = where(pdc['convdc'][:,CONVSTATUS] == 1)[0].astype(int) slackdc = where(pdc['convdc'][:,CONVTYPE_DC] == DCSLACK)[0].astype(int) droopdc = where(pdc['convdc'][:,CONVTYPE_DC] == DCDROOP)[0].astype(int) ngriddc = pdc['busdc'][:,GRIDDC].max() ## convert to internal indexing baseMVA, bus, gen, branch = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] baseMVAac, baseMVAdc, pol, busdc, convdc, branchdc = \ pdc["baseMVAac"], pdc["baseMVAdc"], pdc["pol"], \ pdc["busdc"], pdc["convdc"], pdc["branchdc"] ##----- Violation check ----- ## dc slack bus and distributed voltage bus violation check gridviol = setdiff1d(arange(1,ngriddc+1),busdc[r_[slackdc, droopdc],GRIDDC]) if not gridviol.size == 0: stdout.write('\nMultiple dc slack busses defined in grid %d \n' % (gridviol)) stderr.write('No droop controlled bus or slack bus defined for every dc grid !\n') ## remove multiple slack buses if multslack == 0: for ii in arange(1,ngriddc+1): slackdcii = intersect1d(slackdc,where(busdc[:,GRIDDC] == ii)[0]) if slackdcii.size > 1: convdc[slackdcii[0].astype(int),CONVTYPE_DC ] = DCSLACK convdc[slackdcii[1:].astype(int),CONVTYPE_DC ] = DCNOSLACK slackdcii = slackdcii[0] ## printout changes stdout.write('\nMultiple dc slack busses defined in grid %d' %(ii)) stdout.write('\n Bus %d kept as the slack bus\n'%\ (i2edc[slackdcii.astype(int)+1])) ## redefine slack buses slackdc = where(convdc[:,CONVTYPE_DC] == DCSLACK)[0].astype(int) ## define indices of slack, droop and power controlled buses slackdroopdc = union1d(slackdc, droopdc) noslackbdc = setdiff1d(where(busdc[:,BUSDC_I]), slackdc) ## remove converter and generator V control violations vcontrvsc = where(convdc[:,CONVTYPE_AC] == PVC)[0] vcontrgen = r_[where(bus[:,BUS_TYPE] == PV)[0], \ where(bus[:,BUS_TYPE] == REF)[0]] ## buses with V control conflicts vconfl = intersect1d(vcontrvsc, vcontrgen).astype(int) convdc[vconfl,CONVTYPE_AC] = PQC convdc[vconfl,QCONV] = 0 convdc[:,QCONV] *= convdc[:,CONVTYPE_AC] == PQC if not vconfl.size == 0: stdout.write('Generator & VSC converter on the same bus') stdout.write('\n Conflicting voltage control on bus %d' %(i2eac[vconfl+1])) stdout.write('\n=> Corresponding VSC Converter set to PQ control without Q injections.\n') ##----- initialisation ac network ----- ## dummy generator initialisation Vcref = convdc[:,VCONV] # voltage setpoints busVSC = bus.copy() gendm = zeros((0,gen.shape[1])) genPQ = zeros((0,1)).astype(int) genPQi = zeros((0,1)).astype(int) Qcmin_dum = -99999 Qcmax_dum = 99999 Pcmin_dum = 0 Pcmax_dum = 99999 ## dummy generator addition for ii in arange(convdc.shape[0]): ## change control from PQ to PV for buses with converter in PV control if bus[ii,BUS_TYPE] == PQ and convdc[ii,CONVTYPE_AC] == PVC: busVSC[ii,BUS_TYPE] = PV ## add dummy generator to V controlling converter bus without generator if not any(gen[:,GEN_BUS] == bus[ii,BUS_I]): gendm = r_[gendm, zeros((1,gen.shape[1]))] gendm[-1,[GEN_BUS,PG,QG,QMAX,QMIN,VG,MBASE,GEN_STATUS,PMAX,PMIN]] = \ [ii+1,0,0,Qcmax_dum,Qcmin_dum,Vcref[ii],baseMVAac,1,Pcmax_dum,Pcmin_dum] else: genPQ = r_[genPQ,bus[ii,BUS_I]] genPQii = where(gen[:,GEN_BUS] == bus[ii,BUS_I])[0] genPQi = r_[genPQi,genPQii] ## define buses with dummy generator # gdmbus = where(gendm[[where(bus[:,BUS_I]==x)[0][0] for x in \ # gendm[:,GEN_BUS]],GEN_BUS])[0] if any(gendm[:,GEN_BUS]): gdmbus = where(gendm[:,GEN_BUS] == bus[:,BUS_I])[0] else: gdmbus = [] ## converter stations power injections into ac network Pvsc = convdc[:,PCONV]/baseMVA Qvsc = convdc[:,QCONV]/baseMVA ## dc voltage droop setpoints and parameters PVdroop = zeros(busdc.shape[0]) Pdcset = zeros(busdc.shape[0]) Vdcset = zeros(busdc.shape[0]) dVdcset = zeros(busdc.shape[0]) PVdroop[cdci] = convdc[cdci,DROOP]*baseMVA Pdcset[cdci] = convdc[cdci,PDCSET]/baseMVA Vdcset[cdci] = convdc[cdci,VDCSET] dVdcset[cdci] = convdc[cdci,DVDCSET] ## voltage droop converter power initialisation Pvsc[droopdc] = Pdcset[droopdc] ## assumption: operating in reference set-point & no converter losses ## dc slack converter power injection initialisation if slackdc.size != 0: for ii in arange(1,ngriddc+1): #slackdcii = where(convdc[busdc[:,GRIDDC]==ii,CONVTYPE_DC]==DCSLACK)[0] slackdcii = intersect1d(where(busdc[:,GRIDDC]==ii)[0],\ where(convdc[:,CONVTYPE_DC]==DCSLACK)[0]) if slackdcii.size != 0: #Pvscii = Pvsc*(convdc[busdc[:,GRIDDC]==1,CONVTYPE_DC]!=DCSLACK) Pvscii = Pvsc*(equal(busdc[:,GRIDDC],ii)* \ not_equal(convdc[:,CONVTYPE_DC],DCSLACK)) Pvsc[slackdcii] = -Pvscii.sum()/slackdcii.shape[0] ## Inclusion of converters as loads busVSC[cdci,PD] = bus[cdci,PD] - Pvsc[cdci]*baseMVA busVSC[cdci,QD] = bus[cdci,QD] - Qvsc[cdci]*baseMVA ##----- initialisation of converter quantities ----- ## per unit converter loss coefficients values basekA = baseMVA/(sqrt(3)*convdc[:,BASEKVC]) lossa = convdc[:,LOSSA]/baseMVA lossb = convdc[:,LOSSB]*basekA/baseMVA losscr = convdc[:,LOSSCR]*basekA**2/baseMVA lossci = convdc[:,LOSSCI]*basekA**2/baseMVA ## converter reactor parameters Rc = convdc[:,RCONV] Xc = convdc[:,XCONV] Zc = Rc+j*Xc ## converter limits data Icmax = convdc[:,ICMAX] Vcmax = convdc[:,VCMAX] Vcmin = convdc[:,VCMIN] ## filter reactance Bf = convdc[:,BF] ## transformer parameters Rtf = convdc[:,RTF] Xtf = convdc[:,XTF] Ztf = Rtf+j*Xtf ##----- initialisation of dc network quantities ----- ## build dc bus matrix Ybusdc, Yfdc, Ytdc = makeYbusdc( busdc, branchdc ) ## detect ac islands errors (non-synchronised zones => to be solved independently) zonecheck(bus, gen, branch, i2eac, output) aczones = sort(unique(bus[:,ZONE])).astype(int) ##----- main iteration loop ----- ## initialise Vdc = busdc[:,VDC] #dc bus voltages genVSC = r_[gen, gendm] #inclusion of dummy generators for ac solution gendmidx = where(genVSC[:,GEN_BUS] == setdiff1d(genVSC[:,GEN_BUS], gen[:, GEN_BUS]))[0] # index of dummy generators in genVSC matrix Ps = Pvsc #grid side converter power initialisation Pdc = zeros(busdc.shape[0]) Ifdc = zeros(branchdc.shape[0]) Pfdc = zeros(branchdc.shape[0]) Ptdc = zeros(branchdc.shape[0]) ## iteration options it = 0 converged = 0 ## main loop while (not converged) and (it <= itmaxacdc): ## update iteration counter it += 1 ## reset grid side converter reactive power injection Qs = Qvsc Ss = Ps +j*Qs ##----- ac network power flow ----- ## ac power flow with converters as loads (PQ mode) or load+generator (PV mode) busVSCext = zeros((0,bus.shape[1])) genVSCext = zeros((0,gen.shape[1])) branchext = zeros((0,QT+1)) buszi = [] genVSCzi = [] brchzi = [] for i in arange(aczones.size): ## select buses, generators and branches in the specified ac zone buszi = where(bus[:,ZONE] == aczones[i])[0] genVSCzi = where(bus[[where(bus[:,BUS_I]==x)[0][0] for x in \ genVSC[:,GEN_BUS]],ZONE] == aczones[i])[0] brchzi = where(bus[[where(bus[:,BUS_I]==x)[0][0] for x in \ branch[:,F_BUS]],ZONE] == aczones[i])[0] busVSCz = busVSC[buszi,:] genVSCz = genVSC[genVSCzi,:] branchz = branch[brchzi,:] ## solve ac power flow for specified ac zone (if not infinite bus) if busVSCz.shape[0]>1: accaseVSCz = {} accaseVSCz['baseMVA'] = baseMVA accaseVSCz['bus'] = busVSCz accaseVSCz['gen'] = genVSCz accaseVSCz['branch'] = branchz resultsz,successz = runpf(accaseVSCz, ppopt) busVSCz = resultsz['bus'] genVSCz = resultsz['gen'] branchz = resultsz['branch'] ## store solutions for specified ac zone in extended matrices for k,idx in enumerate(buszi): if busVSCext.shape[0] <= idx: busVSCext = r_[busVSCext,zeros((idx-busVSCext.shape[0]+1, \ bus.shape[1]))] busVSCext[idx,:] = busVSCz[k,:] for k,idx in enumerate(genVSCzi): if genVSCext.shape[0] <= idx: genVSCext = r_[genVSCext,zeros((idx-genVSCext.shape[0]+1, \ gen.shape[1]))] genVSCext[idx,:] = genVSCz[k,:] for k,idx in enumerate(brchzi): if branchext.shape[0] <= idx: branchext = r_[branchext,zeros((idx-branchext.shape[0]+1, \ QT+1))] branchext[idx,:] = branchz[k,:] busVSC = busVSCext.copy() genVSC = genVSCext.copy() branch = branchext.copy() ## dummy generator update gendm = genVSC[gen.shape[0]:,:] ## dummy generator on converter V controlled bus Ss[gdmbus] = Ss[gdmbus] + j*gendm[:,QG]/baseMVA ## PQ generator on converter V controlled bus Ss[genPQ] = Ss[genPQ] + \ j*(genVSC[genPQi,QG] - gen[genPQi,QG])/baseMVA ## update grid side converter power injections Ps = real(Ss) Qs = imag(Ss) ## generator reset genVSC[gendmidx,QG] = 0 genVSC[genPQi,QG] = gen[genPQi,QG] ##----- Converter calculations ----- ## converter reactor voltages and power Vs = busVSC[bdci,VM]*exp(j*busVSC[bdci,VA]*pi/180) Itf = conj(Ss/Vs) ## transformer current Vf = Vs + Itf*Ztf ## filter side voltage Ssf = Vf*conj(Itf) ## filter side transformer complex power Qf = -Bf*abs(Vf)**2 ## filter reactive power Scf = Ssf + j*Qf ## filter side converter complex power Ic = conj(Scf/Vf) ## converter current Vc = Vf + Ic*Zc ## converter side voltage Sc = Vc*conj(Ic) ## converter side complex power ## converter active and reactive powers Pc = real(Sc) Qc = imag(Sc) Pcf = real(Scf) Qcf = imag(Scf) Psf = real(Ssf) Qsf = imag(Ssf) ## initialisation Ps_old = Ps.copy() if limac == 1: ##--- converter limit check --- ## initialisation limviol = zeros((busdc.shape[0])) SsL = zeros((busdc.shape[0]),dtype=complex) plotarg = zeros((busdc.shape[0],17),dtype=complex) for ii in arange(1,ngriddc+1): ## remove slack converters from limit check cdcii = where(busdc[:,GRIDDC] == ii)[0] ccdcslackii = where(intersect1d(cdcii,slackdc)==cdcii)[0] if not ccdcslackii.size == 0: cdcii = delete(cdcii,ccdcslackii) #remove slack converter cdci0 = where(convdc[cdcii,CONV_BUS]==0)[0] cdcii = delete(cdcii,cdci0) # remove zero elements (converter outages) ## converter limit check for jj in arange(cdcii.size): cvjj = cdcii[jj] limviol[cvjj],SsL[cvjj], plotarg[cvjj,:] = convlim(Ss[cvjj], \ Vs[cvjj], Vc[cvjj], Ztf[cvjj], Bf[cvjj], Zc[cvjj], \ Icmax[cvjj], Vcmax[cvjj], Vcmin[cvjj], i2edc[cvjj+1], \ tollim, convplotopt) ## converter limit violations (1 = Q limit, 2 = P limit) limviolii = limviol*(busdc[:,GRIDDC] == ii) dSii = (SsL-Ss)*(busdc[:,GRIDDC] == ii)*(convdc[:,CONVTYPE_DC] != DCSLACK) if (2 in limviolii) or (1 in limviolii): if (2 in limviolii): dSii = dSii*(limviolii==2) dSiimaxi = where(abs(real(dSii)).max())[0] stdout.write('\n Active power setpoint of converter %d changed from %.2f MW to %.2f MW.'%( \ i2edc[dSiimaxi+1], real(Ss[dSiimaxi])*baseMVA, real(SsL[dSiimaxi])*baseMVA)) stdout.write('\n Reactive power setpoint of converter %d changed from %.2f MVAr to %.2f MVAr.\n'%(\ i2edc[dSiimaxi+1], imag(Ss[dSiimaxi])*baseMVA, imag(SsL[dSiimaxi])*baseMVA)) else: ## if ismember(1, limviolii) dSii = dSii*(limviolii==1) dSiimaxi = argmax(abs(imag(dSii))) stdout.write('\n Reactive power setpoint of converter %d changed from %.2f MVAr to %.2f MVAr. \n'%(\ i2edc[dSiimaxi+1], imag(Ss[dSiimaxi])*baseMVA, imag(SsL[dSiimaxi])*baseMVA)) ## plot converter setpoint adaptation if convplotopt != 0 : convlimplot(plotarg[dSiimaxi,:], i2edc[dSiimaxi]) ## update converter powers Ss[dSiimaxi] = SsL[dSiimaxi] Pvsc[dSiimaxi] = real(Ss[dSiimaxi]) Qvsc[dSiimaxi] = imag(Ss[dSiimaxi]) busVSC[dSiimaxi,PD] = bus[dSiimaxi,PD] - \ Pvsc[dSiimaxi]*baseMVA ## converter P injection from input files included as load busVSC[dSiimaxi,QD] = bus[dSiimaxi,QD] - \ Qvsc[dSiimaxi]*baseMVA ## only Q from input files is included, not for V control else: dSiimaxi = [] ## Remove voltage control on violated converter if convdc[dSiimaxi, CONVTYPE_AC]==PVC: convdc[dSiimaxi, CONVTYPE_AC] = PQC stdout.write(' Voltage control at converter bus %d removed.\n'% i2edc[dSiimaxi+1]) busVSC[dSiimaxi, BUS_TYPE] = PQ ## Remove dummy generator (PV bus changed to PQ bus) if dSiimaxi in gdmbus: dSidx = where(gdmbus == dSiimaxi)[0] dSgenidx = gendmidx[dSidx] gendm = delete(gendm,dSidx) genVSC = delete(genVSC,dSgenidx) gdmbus = delete(gdmbus,dSidx) gendmidx = where(genVSC[:,GEN_BUS] == np.setdiff1d(genVSC[:, GEN_BUS],gen[:, GEN_BUS])) ## index of dummy generators in genVSC matrix ## Remove VSC voltage control at genPQ bus if dSiimaxi in genPQ: dSidx = where(genPQ == dSiimaxi)[0] genPQ = delete(genPQ,dSidx) genPQi = delete(genPQi,dSidx) ## Remove droop control on violated converter if convdc[dSiimaxi, CONVTYPE_DC]==DCDROOP: convdc[dSiimaxi, CONVTYPE_DC] = DCNOSLACK droopdc = setdiff1d(droopdc,dSiimaxi) ## remove converter from droop converters slackdroopdc = setdiff1d(slackdroopdc,dSiimaxi) ## remove converter from slack/droop converters (additional loss iteration) stdout.write(' Droop control at converter bus %d disabled.\n'%i2edc[dSiimaxi+1]) ## recalculate converter quantities after limit check Itf = conj(Ss/Vs) ## transformer current Vf = Vs + Itf*Ztf ## filter side voltage Ssf = Vf*conj(Itf) ## filter side transformer complex power Qf = -Bf*abs(Vf)**2 ## filter reactive power Scf = Ssf + j*Qf ## filter side converter complex power Ic = conj(Scf/Vf) ## converter current Vc = Vf + Ic*Zc ## converter side voltage Sc = Vc*conj(Ic) ## converter side complex power ## converter active and reactive powers after limit check Ps = real(Ss) Qs = imag(Ss) Pc = real(Sc) Qc = imag(Sc) Pcf = real(Scf) Qcf = imag(Scf) Psf = real(Ssf) Qsf = imag(Ssf) ## converter losses and dc side power Ploss = calclossac(Pc, Qc, Vc, lossa, lossb, losscr, lossci) Pdc[cdci] = Pc[cdci] + Ploss[cdci] ##----- dc networks power flow ----- ## calculate dc networks Vdc, Pdc = dcnetworkpf(Ybusdc, Vdc, Pdc,slackdc, noslackbdc,\ droopdc, PVdroop, Pdcset, Vdcset, dVdcset, pol, toldc, itmaxdc) ## calculate dc line powers Ifdc = Yfdc*Vdc ## current through dc lines Vdcf = Vdc[[where(busdc[:,BUSDC_I]==x)[0][0] for x in \ branchdc[:,F_BUSDC]]] Vdct = Vdc[[where(busdc[:,BUSDC_I]==x)[0][0] for x in \ branchdc[:,T_BUSDC]]] Pfdc = pol*Vdcf*Ifdc ## power at the "from" bus Ptdc = pol*Vdct*(-Ifdc) ## power at the "to" bus ##----- slack/droop bus voltage and converter loss ----- ## Initialisation Pc[slackdroopdc] = Pdc[slackdroopdc] - Ploss[slackdroopdc] ## Pc initialisation itslack = 0 convergedslackdroop = 0 ## dc slack bus loss calculation while not convergedslackdroop and itslack<=itmaxslackdroop: ## update iteration counter and convergence variable itslack += 1 Pcprev = Pc.copy() ## update slack bus powers Ps, Qc and voltage Vc Ps[slackdroopdc], Qc[slackdroopdc], Vc[slackdroopdc] = calcslackdroop( Pc[slackdroopdc], Qs[slackdroopdc], Vs[slackdroopdc], \ Vf[slackdroopdc], Vc[slackdroopdc], Ztf[slackdroopdc], \ Bf[slackdroopdc], Zc[slackdroopdc], \ tolslackdroopint, itmaxslackdroopint) ## update slack bus losses Ploss[slackdroopdc] = calclossac(Pc[slackdroopdc], Qc[slackdroopdc], \ Vc[slackdroopdc], lossa[slackdroopdc], lossb[slackdroopdc], \ losscr[slackdroopdc], lossci[slackdroopdc]) ## update slack bus converter side power Pc Pc[slackdroopdc] = Pdc[slackdroopdc] - Ploss[slackdroopdc] ## slack bus tolerance check if max(abs(Pcprev[slackdroopdc] - Pc[slackdroopdc])) < tolslackdroop: convergedslackdroop = 1 if not convergedslackdroop: stdout.write('\nSlackbus/Droop converter loss calculation of grid did NOT converge in %d iterations\n'% itslack) ## extended bus matrix update busVSC[cdci,PD] = bus[cdci,PD] - Ps[cdci]*baseMVA ## convergence check if abs(Ps_old - Ps).max() < tolacdc: converged = 1 ## end of iteration timecalc = time() - t0 ##----- Post processing ----- ## convergence if converged: if output: stdout.write('\nSequential solution method converged in %d iterations\n'%it) else: stdout.write('\nSequential solution method did NOT converge after %d iterations\n'%it) ## converter limit check if limac == 1: for ii in arange(cdci.size): cvii = cdci[ii] limviol, _, plotarg = convlim(Ss[cvii], Vs[cvii], Vc[cvii], Ztf[cvii], \ Bf[cvii], Zc[cvii], Icmax[cvii], Vcmax[cvii], Vcmin[cvii], i2edc[cvii+1], tollim, 1) if limviol != 0: ## limits are hit if (convdc[cvii,CONVTYPE_DC] == DCSLACK): stdout.write('\n Slackbus converter %d is operating outside its limits.\n'%i2edc[cvii+1]) elif (convdc[cvii,CONVTYPE_DC] == DCNOSLACK): stdout.write('\n Converter %d is operating outside its limits.\n'%i2edc[cvii+1]) if convplotopt == 2 : convlimplot(plotarg, i2edc[cvii]) ## update bus matrix bus[:,VM] = busVSC[:,VM] bus[:,VA] = busVSC[:,VA] ## dummy generators removal gen = genVSC[arange(gen.shape[0]),:] ## update busdc matrix busdc[:,PDC] = Pdc*baseMVA busdc[:,VDC] = Vdc ## update convdc matrix convdc[:,PCONV] = Ps*baseMVA convdc[:,QCONV] = Qs*baseMVA # new addition to convdc matrix convdc = c_[convdc,abs(Vc)] convdc = c_[convdc,angle(Vc)*180/pi] convdc = c_[convdc,Pc*baseMVA] convdc = c_[convdc,Qc*baseMVA] convdc = c_[convdc,Ploss*baseMVA] convdc = c_[convdc,abs(Vf)] convdc = c_[convdc,angle(Vf)*180/pi] convdc = c_[convdc,Psf*baseMVA] convdc = c_[convdc,Qsf*baseMVA] convdc = c_[convdc,Qcf*baseMVA] ## new addition to branchdc matrix branchdc = c_[branchdc,Pfdc*baseMVA] branchdc = c_[branchdc,Ptdc*baseMVA] #----- internal to external bus renumbering ----- # remove dummy converters convdc = convdc[cdci,:] ## convert to external indexing ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] = \ baseMVA, bus, gen, branch pdc["baseMVAac"], pdc["baseMVAdc"], pdc["pol"], \ pdc["busdc"], pdc["convdc"], pdc["branchdc"] = \ baseMVAac, baseMVAdc, pol, busdc, convdc, branchdc ## Per unit internal to external data conversion pdc =int2extpu(ppc['baseMVA'],pdc); ## Undo the matrices sorting based on the bus numbers ppc['bus'] = ppc['bus'][i2ebus.argsort(),:] ppc['gen'] = ppc['gen'][i2egen.argsort(),:] ppc['branch'] = ppc['branch'][i2ebrch.argsort(),:] pdc['busdc'] = pdc['busdc'][i2ebusdc.argsort(),:] pdc['convdc'] = pdc['convdc'][i2econvdc.argsort(),:] pdc['branchdc'] = pdc['branchdc'][i2ebrchdc.argsort(),:] ## ac network internal to external bus numbering pdc, ppc = int2extac(i2eac, acdmbus, pdc, ppc) ## dc network internal to external bus numbering pdc = int2extdc(i2edcpmt, i2edc, pdc) ## generator outage inclusion gen1 = ppc['gen'] ## operational generators gen0[:,[PG, QG]] = 0 ## reset generator power injection ppc['gen'] = zeros((gon.shape[0]+goff.shape[0], gen1.shape[1])); ppc['gen'][gon,:] = gen1 ## include operational generators ppc['gen'][goff,:] = gen0 ## include non-operational generators ## converter with outages inclusion conv1 = pdc['convdc'] conv0 = c_[conv0, zeros((conv0.shape[0],conv1.shape[1] - conv0.shape[1]))] pdc['convdc'][conv0i, :] = conv0 pdc['convdc'][conv1i, :] = conv1 if conv0busi.shape[0]>0: pdc['busdc'][conv0busi[:,0], BUSAC_I] = conv0busi[:,1] ## dc branch outages inclusion brchdc1 = pdc['branchdc'] brchdc0 = c_[brchdc0, zeros((brchdc0.shape[0], brchdc1.shape[1] - brchdc0.shape[1]))] pdc['branchdc'][brchdc0i,:] = brchdc0 pdc['branchdc'][brchdc1i,:] = brchdc1 ## ac branch outages inclusion if ppc['branch'].shape[0] == 0: ## all infinite buses # python start the index at 0 brch0 = c_[brch0, zeros((brch0.shape[0], QT + 1 - brch0.shape[1]))] # not necessary anymore after rewriting the code ppc['branch'] = brch0; else: brch1 = ppc['branch'] brch0 = c_[brch0, zeros((brch0.shape[0], brch1.shape[1] - brch0.shape[1]))]; ppc['branch'][brch0i,:] = brch0 ppc['branch'][brch1i,:] = brch1 ##----- output results ----- ## print results if output: printpf(ppc['baseMVA'], ppc['bus'], ppc['gen'], ppc['branch'],None,converged,timecalc) printdcpf(pdc['busdc'], pdc['convdc'], pdc['branchdc']) ##----- output results ----- # as dict resultsac = {} resultsac['baseMVA'] = baseMVA resultsac['bus'] = bus resultsac['gen'] = gen resultsac['branch'] = branch resultsdc = {} resultsdc['baseMVAac'] = baseMVAac resultsdc['baseMVAdc'] = baseMVAdc resultsdc['pol'] = pol resultsdc['busdc'] = busdc resultsdc['convdc'] = convdc resultsdc['branchdc'] = branchdc # if nargout == 2 || nargout == 3 || nargout == 4 # baseMVA = resultsac; # bus = resultsdc; # gen = converged; # branch = timecalc; # end input() return resultsac, resultsdc, converged, timecalc
def t_runopf_w_res(quiet=False): """Tests C{runopf_w_res} and the associated callbacks. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ t_begin(46, quiet) verbose = 0#not quiet tdir = dirname(__file__) casefile = join(tdir, 't_case30_userfcns') ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=560) t = 'runopf_w_res(''t_case30_userfcns'') : ' r = runopf_w_res(casefile, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 7, [t, 'mu.Pmax']) ppc = loadcase(casefile) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t = 'gen 5 no reserves : '; ppc = loadcase(casefile) ppc['reserves']['zones'][:, 4] = 0 ppc['reserves']['cost'] = delete(ppc['reserves']['cost'], 4) ppc['reserves']['qty'] = delete(ppc['reserves']['qty'], 4) r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 0, 20], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 0, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 6, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 187.5, 4, [t, 'totalcost']) t = 'extra offline gen : '; ppc = loadcase(casefile) idx = list(range(3)) + [4] + list(range(3, 6)) ppc['gen'] = ppc['gen'][idx, :] ppc['gencost'] = ppc['gencost'][idx, :] ppc['reserves']['zones'] = ppc['reserves']['zones'][:, idx] ppc['reserves']['cost'] = ppc['reserves']['cost'][idx] ppc['reserves']['qty'] = ppc['reserves']['qty'][idx] ppc['gen'][3, GEN_STATUS] = 0 r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 0, 19.3906, 0.6094], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 5.5, 2, 5.5, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 0, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0, 0.5, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t = 'both extra & gen 6 no res : '; ppc = loadcase(casefile) idx = list(range(3)) + [4] + list(range(3, 6)) ppc['gen'] = ppc['gen'][idx, :] ppc['gencost'] = ppc['gencost'][idx, :] ppc['reserves']['zones'] = ppc['reserves']['zones'][:, idx] ppc['reserves']['cost'] = ppc['reserves']['cost'][idx] ppc['reserves']['qty'] = ppc['reserves']['qty'][idx] ppc['gen'][3, GEN_STATUS] = 0 ppc['reserves']['zones'][:, 5] = 0 ppc['reserves']['cost'] = delete(ppc['reserves']['cost'], 5) ppc['reserves']['qty'] = delete(ppc['reserves']['qty'], 5) r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 0, 0, 20], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 5.5, 2, 0, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 0, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0, 0], 6, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0, 0, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 187.5, 4, [t, 'totalcost']) t = 'no qty (Rmax) : ' ppc = loadcase(casefile) del ppc['reserves']['qty'] r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [39.3826, 0.6174, 0, 0, 19.3818, 0.6182], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 5, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 5, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0.1, 0, 0, 0, 0.5, 0], 5, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['totalcost'], 176.3708, 4, [t, 'totalcost']) t = 'RAMP_10, no qty (Rmax) : '; ppc = loadcase(casefile) del ppc['reserves']['qty'] ppc['gen'][0, RAMP_10] = 25 r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t_end()
def t_jacobian(quiet=False): """Numerical tests of partial derivative code. @author: Ray Zimmerman (PSERC Cornell) """ t_begin(28, quiet) ## run powerflow to get solved case ppopt = ppoption(VERBOSE=0, OUT_ALL=0) ppc = loadcase(case30()) results, _ = runpf(ppc, ppopt) baseMVA, bus, gen, branch = \ results['baseMVA'], results['bus'], results['gen'], results['branch'] ## switch to internal bus numbering and build admittance matrices _, bus, gen, branch = ext2int1(bus, gen, branch) Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch) Ybus_full = Ybus.todense() Yf_full = Yf.todense() Yt_full = Yt.todense() Vm = bus[:, VM] Va = bus[:, VA] * (pi / 180) V = Vm * exp(1j * Va) f = branch[:, F_BUS].astype(int) ## list of "from" buses t = branch[:, T_BUS].astype(int) ## list of "to" buses #nl = len(f) nb = len(V) pert = 1e-8 Vm = array([Vm]).T # column array Va = array([Va]).T # column array Vc = array([V]).T # column array ##----- check dSbus_dV code ----- ## full matrices dSbus_dVm_full, dSbus_dVa_full = dSbus_dV(Ybus_full, V) ## sparse matrices dSbus_dVm, dSbus_dVa = dSbus_dV(Ybus, V) dSbus_dVm_sp = dSbus_dVm.todense() dSbus_dVa_sp = dSbus_dVa.todense() ## compute numerically to compare Vmp = (Vm * ones((1, nb)) + pert*eye(nb)) * (exp(1j * Va) * ones((1, nb))) Vap = (Vm * ones((1, nb))) * (exp(1j * (Va*ones((1, nb)) + pert*eye(nb)))) num_dSbus_dVm = (Vmp * conj(Ybus * Vmp) - Vc * ones((1, nb)) * conj(Ybus * Vc * ones((1, nb)))) / pert num_dSbus_dVa = (Vap * conj(Ybus * Vap) - Vc * ones((1, nb)) * conj(Ybus * Vc * ones((1, nb)))) / pert t_is(dSbus_dVm_sp, num_dSbus_dVm, 5, 'dSbus_dVm (sparse)') t_is(dSbus_dVa_sp, num_dSbus_dVa, 5, 'dSbus_dVa (sparse)') t_is(dSbus_dVm_full, num_dSbus_dVm, 5, 'dSbus_dVm (full)') t_is(dSbus_dVa_full, num_dSbus_dVa, 5, 'dSbus_dVa (full)') ##----- check dSbr_dV code ----- ## full matrices dSf_dVa_full, dSf_dVm_full, dSt_dVa_full, dSt_dVm_full, _, _ = \ dSbr_dV(branch, Yf_full, Yt_full, V) ## sparse matrices dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St = dSbr_dV(branch, Yf, Yt, V) dSf_dVa_sp = dSf_dVa.todense() dSf_dVm_sp = dSf_dVm.todense() dSt_dVa_sp = dSt_dVa.todense() dSt_dVm_sp = dSt_dVm.todense() ## compute numerically to compare Vmpf = Vmp[f, :] Vapf = Vap[f, :] Vmpt = Vmp[t, :] Vapt = Vap[t, :] Sf2 = (Vc[f] * ones((1, nb))) * conj(Yf * Vc * ones((1, nb))) St2 = (Vc[t] * ones((1, nb))) * conj(Yt * Vc * ones((1, nb))) Smpf = Vmpf * conj(Yf * Vmp) Sapf = Vapf * conj(Yf * Vap) Smpt = Vmpt * conj(Yt * Vmp) Sapt = Vapt * conj(Yt * Vap) num_dSf_dVm = (Smpf - Sf2) / pert num_dSf_dVa = (Sapf - Sf2) / pert num_dSt_dVm = (Smpt - St2) / pert num_dSt_dVa = (Sapt - St2) / pert t_is(dSf_dVm_sp, num_dSf_dVm, 5, 'dSf_dVm (sparse)') t_is(dSf_dVa_sp, num_dSf_dVa, 5, 'dSf_dVa (sparse)') t_is(dSt_dVm_sp, num_dSt_dVm, 5, 'dSt_dVm (sparse)') t_is(dSt_dVa_sp, num_dSt_dVa, 5, 'dSt_dVa (sparse)') t_is(dSf_dVm_full, num_dSf_dVm, 5, 'dSf_dVm (full)') t_is(dSf_dVa_full, num_dSf_dVa, 5, 'dSf_dVa (full)') t_is(dSt_dVm_full, num_dSt_dVm, 5, 'dSt_dVm (full)') t_is(dSt_dVa_full, num_dSt_dVa, 5, 'dSt_dVa (full)') ##----- check dAbr_dV code ----- ## full matrices dAf_dVa_full, dAf_dVm_full, dAt_dVa_full, dAt_dVm_full = \ dAbr_dV(dSf_dVa_full, dSf_dVm_full, dSt_dVa_full, dSt_dVm_full, Sf, St) ## sparse matrices dAf_dVa, dAf_dVm, dAt_dVa, dAt_dVm = \ dAbr_dV(dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St) dAf_dVa_sp = dAf_dVa.todense() dAf_dVm_sp = dAf_dVm.todense() dAt_dVa_sp = dAt_dVa.todense() dAt_dVm_sp = dAt_dVm.todense() ## compute numerically to compare num_dAf_dVm = (abs(Smpf)**2 - abs(Sf2)**2) / pert num_dAf_dVa = (abs(Sapf)**2 - abs(Sf2)**2) / pert num_dAt_dVm = (abs(Smpt)**2 - abs(St2)**2) / pert num_dAt_dVa = (abs(Sapt)**2 - abs(St2)**2) / pert t_is(dAf_dVm_sp, num_dAf_dVm, 4, 'dAf_dVm (sparse)') t_is(dAf_dVa_sp, num_dAf_dVa, 4, 'dAf_dVa (sparse)') t_is(dAt_dVm_sp, num_dAt_dVm, 4, 'dAt_dVm (sparse)') t_is(dAt_dVa_sp, num_dAt_dVa, 4, 'dAt_dVa (sparse)') t_is(dAf_dVm_full, num_dAf_dVm, 4, 'dAf_dVm (full)') t_is(dAf_dVa_full, num_dAf_dVa, 4, 'dAf_dVa (full)') t_is(dAt_dVm_full, num_dAt_dVm, 4, 'dAt_dVm (full)') t_is(dAt_dVa_full, num_dAt_dVa, 4, 'dAt_dVa (full)') ##----- check dIbr_dV code ----- ## full matrices dIf_dVa_full, dIf_dVm_full, dIt_dVa_full, dIt_dVm_full, _, _ = \ dIbr_dV(branch, Yf_full, Yt_full, V) ## sparse matrices dIf_dVa, dIf_dVm, dIt_dVa, dIt_dVm, _, _ = dIbr_dV(branch, Yf, Yt, V) dIf_dVa_sp = dIf_dVa.todense() dIf_dVm_sp = dIf_dVm.todense() dIt_dVa_sp = dIt_dVa.todense() dIt_dVm_sp = dIt_dVm.todense() ## compute numerically to compare num_dIf_dVm = (Yf * Vmp - Yf * Vc * ones((1, nb))) / pert num_dIf_dVa = (Yf * Vap - Yf * Vc * ones((1, nb))) / pert num_dIt_dVm = (Yt * Vmp - Yt * Vc * ones((1, nb))) / pert num_dIt_dVa = (Yt * Vap - Yt * Vc * ones((1, nb))) / pert t_is(dIf_dVm_sp, num_dIf_dVm, 5, 'dIf_dVm (sparse)') t_is(dIf_dVa_sp, num_dIf_dVa, 5, 'dIf_dVa (sparse)') t_is(dIt_dVm_sp, num_dIt_dVm, 5, 'dIt_dVm (sparse)') t_is(dIt_dVa_sp, num_dIt_dVa, 5, 'dIt_dVa (sparse)') t_is(dIf_dVm_full, num_dIf_dVm, 5, 'dIf_dVm (full)') t_is(dIf_dVa_full, num_dIf_dVa, 5, 'dIf_dVa (full)') t_is(dIt_dVm_full, num_dIt_dVm, 5, 'dIt_dVm (full)') t_is(dIt_dVa_full, num_dIt_dVa, 5, 'dIt_dVa (full)') t_end()
def t_opf_pips(quiet=False): """Tests for PIPS-based AC optimal power flow. @author: Ray Zimmerman (PSERC Cornell) """ num_tests = 101 t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') verbose = 0#not quiet t0 = 'PIPS : ' ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=560) ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## get solved AC power flow case from MAT-file soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf['bus_soln'] gen_soln = soln9_opf['gen_soln'] branch_soln = soln9_opf['branch_soln'] f_soln = soln9_opf['f_soln'][0] ## run OPF t = t0 r = runopf(casefile, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ## run with automatic conversion of single-block pwl to linear costs t = ''.join([t0, '(single-block PWL) : ']) ppc = loadcase(casefile) ppc['gencost'][2, NCOST] = 2 r = runopf(ppc, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) xr = r_[r['var']['val']['Va'], r['var']['val']['Vm'], r['var']['val']['Pg'], r['var']['val']['Qg'], 0, r['var']['val']['y']] t_is(r['x'], xr, 8, [t, 'check on raw x returned from OPF']) ## get solved AC power flow case from MAT-file soln9_opf_Plim = loadmat(join(tdir, 'soln9_opf_Plim.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_Plim['bus_soln'] gen_soln = soln9_opf_Plim['gen_soln'] branch_soln = soln9_opf_Plim['branch_soln'] f_soln = soln9_opf_Plim['f_soln'][0] ## run OPF with active power line limits t = ''.join([t0, '(P line lim) : ']) ppopt1 = ppoption(ppopt, OPF_FLOW_LIM=1) r = runopf(casefile, ppopt1) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ##----- test OPF with quadratic gen costs moved to generalized costs ----- ppc = loadcase(casefile) ppc['gencost'] = array([ [2, 1500, 0, 3, 0.11, 5, 0], [2, 2000, 0, 3, 0.085, 1.2, 0], [2, 3000, 0, 3, 0.1225, 1, 0] ]) r = runopf(ppc, ppopt) bus_soln, gen_soln, branch_soln, f_soln, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] branch_soln = branch_soln[:, :MU_ST + 1] A = None l = array([]) u = array([]) nb = ppc['bus'].shape[0] # number of buses ng = ppc['gen'].shape[0] # number of gens thbas = 0; thend = thbas + nb vbas = thend; vend = vbas + nb pgbas = vend; pgend = pgbas + ng # qgbas = pgend; qgend = qgbas + ng nxyz = 2 * nb + 2 * ng N = sparse((ppc['baseMVA'] * ones(ng), (arange(ng), arange(pgbas, pgend))), (ng, nxyz)) fparm = ones((ng, 1)) * array([[1, 0, 0, 1]]) ix = argsort(ppc['gen'][:, 0]) H = 2 * spdiags(ppc['gencost'][ix, 4], 0, ng, ng, 'csr') Cw = ppc['gencost'][ix, 5] ppc['gencost'][:, 4:7] = 0 ## run OPF with quadratic gen costs moved to generalized costs t = ''.join([t0, 'w/quadratic generalized gen cost : ']) r = opf(ppc, A, l, u, ppopt, N, fparm, H, Cw) f, bus, gen, branch, success = \ r['f'], r['bus'], r['gen'], r['branch'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_is(r['cost']['usr'], f, 12, [t, 'user cost']) ##----- run OPF with extra linear user constraints & costs ----- ## single new z variable constrained to be greater than or equal to ## deviation from 1 pu voltage at bus 1, linear cost on this z ## get solved AC power flow case from MAT-file soln9_opf_extras1 = loadmat(join(tdir, 'soln9_opf_extras1.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_extras1['bus_soln'] gen_soln = soln9_opf_extras1['gen_soln'] branch_soln = soln9_opf_extras1['branch_soln'] f_soln = soln9_opf_extras1['f_soln'][0] row = [0, 0, 1, 1] col = [9, 24, 9, 24] A = sparse(([-1, 1, 1, 1], (row, col)), (2, 25)) u = array([Inf, Inf]) l = array([-1, 1]) N = sparse(([1], ([0], [24])), (1, 25)) ## new z variable only fparm = array([[1, 0, 0, 1]]) ## w = r = z H = sparse((1, 1)) ## no quadratic term Cw = array([100.0]) t = ''.join([t0, 'w/extra constraints & costs 1 : ']) r = opf(casefile, A, l, u, ppopt, N, fparm, H, Cw) f, bus, gen, branch, success = \ r['f'], r['bus'], r['gen'], r['branch'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_is(r['var']['val']['z'], 0.025419, 6, [t, 'user variable']) t_is(r['cost']['usr'], 2.5419, 4, [t, 'user cost']) ##----- test OPF with capability curves ----- ppc = loadcase(join(tdir, 't_case9_opfv2')) ## remove angle diff limits ppc['branch'][0, ANGMAX] = 360 ppc['branch'][8, ANGMIN] = -360 ## get solved AC power flow case from MAT-file soln9_opf_PQcap = loadmat(join(tdir, 'soln9_opf_PQcap.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_PQcap['bus_soln'] gen_soln = soln9_opf_PQcap['gen_soln'] branch_soln = soln9_opf_PQcap['branch_soln'] f_soln = soln9_opf_PQcap['f_soln'][0] ## run OPF with capability curves t = ''.join([t0, 'w/capability curves : ']) r = runopf(ppc, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ##----- test OPF with angle difference limits ----- ppc = loadcase(join(tdir, 't_case9_opfv2')) ## remove capability curves ppc['gen'][ix_(arange(1, 3), [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX])] = zeros((2, 6)) ## get solved AC power flow case from MAT-file soln9_opf_ang = loadmat(join(tdir, 'soln9_opf_ang.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf_ang['bus_soln'] gen_soln = soln9_opf_ang['gen_soln'] branch_soln = soln9_opf_ang['branch_soln'] f_soln = soln9_opf_ang['f_soln'][0] ## run OPF with angle difference limits t = ''.join([t0, 'w/angle difference limits : ']) r = runopf(ppc, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 1, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_is(branch[:, ibr_angmu ], branch_soln[:, ibr_angmu ], 2, [t, 'branch angle mu']) ##----- test OPF with ignored angle difference limits ----- ## get solved AC power flow case from MAT-file soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_opf['bus_soln'] gen_soln = soln9_opf['gen_soln'] branch_soln = soln9_opf['branch_soln'] f_soln = soln9_opf['f_soln'][0] ## run OPF with ignored angle difference limits t = ''.join([t0, 'w/ignored angle difference limits : ']) ppopt1 = ppoption(ppopt, OPF_IGNORE_ANG_LIM=1) r = runopf(ppc, ppopt1) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] ## ang limits are not in this solution data, so let's remove them branch[0, ANGMAX] = 360 branch[8, ANGMIN] = -360 t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) t_end()
from pypower.loadcase import loadcase import matplotlib.pyplot as plt import numpy as np if __name__ == '__main__': ######### # SETUP # ######### print('-----------------------------') print('PYPOWER-Dynamics - Motor Test') print('-----------------------------') # Load PYPOWER case ppc = loadcase('test_case.py') # Program options dynopt = {} dynopt['h'] = 0.01 # step length (s) dynopt['t_sim'] = 10.0 # simulation time (s) dynopt[ 'max_err'] = 0.0001 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 50 # Nominal system frequency (Hz) # Integrator option dynopt['iopt'] = 'mod_euler' #dynopt['iopt'] = 'runge_kutta'
def t_scale_load(quiet=False): """Tests for code in C{scale_load}. @author: Ray Zimmerman (PSERC Cornell) """ n_tests = 275 t_begin(n_tests, quiet) ppc = loadcase(join(dirname(__file__), 't_auction_case')) ppc['gen'][7, GEN_BUS] = 2 ## multiple d. loads per area, same bus as gen ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3]) ## put it load before gen in matrix ppc['gen'] = vstack( [ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]]) ld = find(isload(ppc['gen'])) a = [None] * 3 lda = [None] * 3 for k in range(3): a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1) ## buses in area k tmp = find(in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k])) lda[k] = ld[tmp] ## disp loads in area k area = [None] * 3 for k in range(3): area[k] = {'fixed': {}, 'disp': {}, 'both': {}} area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD]) area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD]) area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN]) area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN]) area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX]) area[k]['disp'][ 'q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax'] area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p'] area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q'] total = {'fixed': {}, 'disp': {}, 'both': {}} total['fixed']['p'] = sum(ppc['bus'][:, PD]) total['fixed']['q'] = sum(ppc['bus'][:, QD]) total['disp']['p'] = -sum(ppc['gen'][ld, PMIN]) total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN]) total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX]) total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax'] total['both']['p'] = total['fixed']['p'] + total['disp']['p'] total['both']['q'] = total['fixed']['q'] + total['disp']['q'] ##----- single load zone, one scale factor ----- load = array([2]) t = 'all fixed loads (PQ) * 2 : ' bus, _ = scale_load(load, ppc['bus']) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all fixed loads (P) * 2 : ' opt = {'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (PQ) * 2 : ' bus, gen = scale_load(load, ppc['bus'], ppc['gen']) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), load * total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), load * total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (P) * 2 : ' opt = {'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (PQ) * 2 : ' opt = {'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), load * total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), load * total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (P) * 2 : ' opt = {'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) ##----- single load zone, one scale quantity ----- load = array([200.0]) t = 'all fixed loads (PQ) => total = 200 : ' opt = {'scale': 'QUANTITY'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) t_is(sum(bus[:, PD]), load, 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load / total['fixed']['p'] * total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'scale': 'QUANTITY', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load - total['disp']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), (load - total['disp']['p']) / total['fixed']['p'] * total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all fixed loads (P) => total = 200 : ' opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) t_is(sum(bus[:, PD]), load, 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load - total['disp']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (PQ) => total = 200 : ' opt = {'scale': 'QUANTITY'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load / total['both']['p'] * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load / total['both']['p'] * total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load / total['both']['p'] * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), load / total['both']['p'] * total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), load / total['both']['p'] * total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (P) => total = 200 : ' opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load / total['both']['p'] * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load / total['both']['p'] * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (PQ) => total = 200 : ' opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load - total['fixed']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), (load - total['fixed']['p']) / total['disp']['p'] * total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), (load - total['fixed']['p']) / total['disp']['p'] * total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (P) => total = 200 : ' opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load - total['fixed']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) ##----- 3 zones, area scale factors ----- t = 'area fixed loads (PQ) * [3 2 1] : ' load = array([3, 2, 1]) bus, _ = scale_load(load, ppc['bus']) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area fixed loads (P) * [3 2 1] : ' load = array([3, 2, 1]) opt = {'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (PQ) * [3 2 1] : ' bus, gen = scale_load(load, ppc['bus'], ppc['gen']) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), load[k] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), load[k] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (P) * [3 2 1] : ' opt = {'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (PQ) * [3 2 1] : ' opt = {'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), load[k] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), load[k] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (P) * [3 2 1] : ' opt = {'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) ##----- 3 zones, area scale quantities ----- t = 'area fixed loads (PQ) => total = [100 80 60] : ' load = array([100, 80, 60], float) opt = {'scale': 'QUANTITY'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] / area[k]['fixed']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'scale': 'QUANTITY', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] - area[k]['disp']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), (load[k] - area[k]['disp']['p']) / area[k]['fixed']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area fixed loads (P) => total = [100 80 60] : ' load = array([100, 80, 60], float) opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] - area[k]['disp']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (PQ) => total = [100 80 60] : ' opt = {'scale': 'QUANTITY'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), load[k] / area[k]['both']['p'] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (P) => total = [100 80 60] : ' opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (PQ) => total = [100 80 60] : throws expected exception' load = array([100, 80, 60], float) opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'} err = 0 try: bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) except ScalingError as e: expected = 'scale_load: impossible to make zone 2 load equal 80 by scaling non-existent dispatchable load' err = expected not in str(e) t_ok(err, t) t = 'area disp loads (PQ) => total = [100 74.3941 60] : ' load = array([100, area[1]['fixed']['p'], 60], float) opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] - area[k]['fixed']['p'], 8, '%s area %d disp P' % (t, k)) if k == 1: t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) else: t_is(-sum(gen[lda[k], QMIN]), (load[k] - area[k]['fixed']['p']) / area[k]['disp']['p'] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), (load[k] - area[k]['fixed']['p']) / area[k]['disp']['p'] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (P) => total = [100 74.3941 60] : ' opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] - area[k]['fixed']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) ##----- explict single load zone ----- t = 'explicit single load zone' load_zone = zeros(ppc['bus'].shape[0]) load_zone[[2, 3]] = 1 load = array([2.0]) bus, gen = scale_load(load, ppc['bus'], ppc['gen'], load_zone) Pd = ppc['bus'][:, PD] Pd[[2, 3]] = load * Pd[[2, 3]] t_is(bus[:, PD], Pd, 8, t) ##----- explict multiple load zone ----- t = 'explicit multiple load zone' load_zone = zeros(ppc['bus'].shape[0]) load_zone[[2, 3]] = 1 load_zone[[6, 7]] = 2 load = array([2, 0.5]) bus, gen = scale_load(load, ppc['bus'], ppc['gen'], load_zone) Pd = ppc['bus'][:, PD] Pd[[2, 3]] = load[0] * Pd[[2, 3]] Pd[[6, 7]] = load[1] * Pd[[6, 7]] t_is(bus[:, PD], Pd, 8, t) t_end()
def t_total_load(quiet=False): """Tests for code in C{total_load}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ n_tests = 48 t_begin(n_tests, quiet) ppc = loadcase(join(dirname(__file__), 't_auction_case')) ppc['gen'][7, GEN_BUS] = 2 ## multiple d. loads per area, same bus as gen ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3]) ## put it load before gen in matrix ppc['gen'] = vstack( [ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]]) ld = find(isload(ppc['gen'])) a = [None] * 3 lda = [None] * 3 for k in range(3): a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1) ## buses in area k tmp = find(in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k])) lda[k] = ld[tmp] ## disp loads in area k area = [None] * 3 for k in range(3): area[k] = {'fixed': {}, 'disp': {}, 'both': {}} area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD]) area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD]) area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN]) area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN]) area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX]) area[k]['disp'][ 'q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax'] area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p'] area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q'] total = {'fixed': {}, 'disp': {}, 'both': {}} total['fixed']['p'] = sum(ppc['bus'][:, PD]) total['fixed']['q'] = sum(ppc['bus'][:, QD]) total['disp']['p'] = -sum(ppc['gen'][ld, PMIN]) total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN]) total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX]) total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax'] total['both']['p'] = total['fixed']['p'] + total['disp']['p'] total['both']['q'] = total['fixed']['q'] + total['disp']['q'] ##----- all load ----- t = 'Pd, _ = total_load(bus) : ' Pd, _ = total_load(ppc['bus']) t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus) : ' Pd, Qd = total_load(ppc['bus']) t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen) : ' Pd, _ = total_load(ppc['bus'], ppc['gen']) t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen) : ' Pd, Qd = total_load(ppc['bus'], ppc['gen']) t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, None, \'all\') : ' Pd, _ = total_load(ppc['bus'], None, 'all') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, None, \'all\') : ' Pd, Qd = total_load(ppc['bus'], None, 'all') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t_is(Qd, total['fixed']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t_is(Qd, total['both']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\', \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\', \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH') t_is(Pd, total['both']['p'], 12, [t, 'Pd']) t_is(Qd, total['both']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\', \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\', \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED') t_is(Pd, total['fixed']['p'], 12, [t, 'Pd']) t_is(Qd, total['fixed']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE') t_is(Pd, total['disp']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE') t_is(Pd, total['disp']['p'], 12, [t, 'Pd']) t_is(Qd, total['disp']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, None, \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'BOTH') t_is(Pd, r_[area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, None, \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'BOTH') t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, None, \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'FIXED') t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, None, \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'FIXED') t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, None, \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE') t_is(Pd, [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, None, \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE') t_is(Pd, [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']], 12, [t, 'Pd']) t_is(Qd, [area[0]['disp']['q'], area[1]['disp']['q'], area[2]['disp']['q']], 12, [t, 'Qd']) ##----- explicit single load zone ----- nb = ppc['bus'].shape[0] load_zone = zeros(nb, int) k = find(ppc['bus'][:, BUS_AREA] == 2) ## area 2 load_zone[k] = 1 t = 'Pd, _ = total_load(bus, gen, load_zone1, \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd']) t_is(Qd, area[1]['both']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone1, \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd']) t_is(Qd, area[1]['fixed']['q'], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd']) t_is(Qd, area[1]['disp']['q'], 12, [t, 'Qd']) ##----- explicit multiple load zone ----- load_zone = zeros(nb, int) k = find(ppc['bus'][:, BUS_AREA] == 3) ## area 3 load_zone[k] = 1 k = find(ppc['bus'][:, BUS_AREA] == 1) ## area 1 load_zone[k] = 2 t = 'Pd, _ = total_load(bus, gen, load_zone2, \'BOTH\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'BOTH\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH') t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd']) t_is(Qd, [area[2]['both']['q'], area[0]['both']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone2, \'FIXED\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'FIXED\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED') t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd']) t_is(Qd, [area[2]['fixed']['q'], area[0]['fixed']['q']], 12, [t, 'Qd']) t = 'Pd, _ = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : ' Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd']) t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : ' Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE') t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd']) t_is(Qd, [area[2]['disp']['q'], area[0]['disp']['q']], 12, [t, 'Qd']) t_end()
def t_dcline(quiet=False): """Tests for DC line extension in L{{toggle_dcline}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ num_tests = 50 t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_dcline') if quiet: verbose = False else: verbose = False t0 = '' ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OPF_ALG=560, OPF_ALG_DC=200) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose) ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## load case ppc0 = loadcase(casefile) del ppc0['dclinecost'] ppc = ppc0 ppc = toggle_dcline(ppc, 'on') ppc = toggle_dcline(ppc, 'off') ndc = ppc['dcline'].shape[0] ## run AC OPF w/o DC lines t = ''.join([t0, 'AC OPF (no DC lines) : ']) r0 = runopf(ppc0, ppopt) success = r0['success'] t_ok(success, [t, 'success']) r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) t_is(r['f'], r0['f'], 8, [t, 'f']) t_is( r['bus'][:,ib_data ], r0['bus'][:,ib_data ], 10, [t, 'bus data']) t_is( r['bus'][:,ib_voltage], r0['bus'][:,ib_voltage], 3, [t, 'bus voltage']) t_is( r['bus'][:,ib_lam ], r0['bus'][:,ib_lam ], 3, [t, 'bus lambda']) t_is( r['bus'][:,ib_mu ], r0['bus'][:,ib_mu ], 2, [t, 'bus mu']) t_is( r['gen'][:,ig_data ], r0['gen'][:,ig_data ], 10, [t, 'gen data']) t_is( r['gen'][:,ig_disp ], r0['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is( r['gen'][:,ig_mu ], r0['gen'][:,ig_mu ], 3, [t, 'gen mu']) t_is(r['branch'][:,ibr_data ], r0['branch'][:,ibr_data ], 10, [t, 'branch data']) t_is(r['branch'][:,ibr_flow ], r0['branch'][:,ibr_flow ], 3, [t, 'branch flow']) t_is(r['branch'][:,ibr_mu ], r0['branch'][:,ibr_mu ], 2, [t, 'branch mu']) t = ''.join([t0, 'AC PF (no DC lines) : ']) ppc1 = {'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()} ppc1['bus'][:, VM] = 1 ppc1['bus'][:, VA] = 0 rp = runpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage']) t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow']) ## run with DC lines t = ''.join([t0, 'AC OPF (with DC lines) : ']) ppc = toggle_dcline(ppc, 'on') r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) expected = array([ [10, 8.9, -10, 10, 1.0674, 1.0935], [2.2776, 2.2776, 0, 0, 1.0818, 1.0665], [0, 0, 0, 0, 1.0000, 1.0000], [10, 9.5, 0.0563, -10, 1.0778, 1.0665] ]) t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V']) expected = array([ [0, 0.8490, 0.6165, 0, 0, 0.2938], [0, 0, 0, 0.4290, 0.0739, 0], [0, 0, 0, 0, 0, 0], [0, 7.2209, 0, 0, 0.0739, 0] ]) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu']) t = ''.join([t0, 'AC PF (with DC lines) : ']) ppc1 = {'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()} ppc1 = toggle_dcline(ppc1, 'on') ppc1['bus'][:, VM] = 1 ppc1['bus'][:, VA] = 0 rp = runpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage']) #t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is( rp['gen'][:2,ig_disp ], r['gen'][:2,ig_disp ], 3, [t, 'gen dispatch']) t_is( rp['gen'][2,PG ], r['gen'][2,PG ], 3, [t, 'gen dispatch']) t_is( rp['gen'][2,QG]+rp['dcline'][0,c.QF], r['gen'][2,QG]+r['dcline'][0,c.QF], 3, [t, 'gen dispatch']) t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow']) ## add appropriate P and Q injections and check angles and generation when running PF t = ''.join([t0, 'AC PF (with equivalent injections) : ']) ppc1 = {'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()} ppc1['bus'][:, VM] = 1 ppc1['bus'][:, VA] = 0 for k in range(ndc): if ppc1['dcline'][k, c.BR_STATUS]: ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS]) tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS]) ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF] ppc1['bus'][ff, QD] = ppc1['bus'][ff, QD] - r['dcline'][k, c.QF] ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT] ppc1['bus'][tt, QD] = ppc1['bus'][tt, QD] - r['dcline'][k, c.QT] ppc1['bus'][ff, VM] = r['dcline'][k, c.VF] ppc1['bus'][tt, VM] = r['dcline'][k, c.VT] ppc1['bus'][ff, BUS_TYPE] = PV ppc1['bus'][tt, BUS_TYPE] = PV rp = runpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage']) t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow']) ## test DC OPF t = ''.join([t0, 'DC OPF (with DC lines) : ']) ppc = ppc0.copy() ppc['gen'][0, PMIN] = 10 ppc['branch'][4, RATE_A] = 100 ppc = toggle_dcline(ppc, 'on') r = rundcopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) expected = array([ [10, 8.9, 0, 0, 1.01, 1], [2, 2, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1], [10, 9.5, 0, 0, 1, 0.98] ]) t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V']) expected = array([ [0, 1.8602, 0, 0, 0, 0], [1.8507, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0.2681, 0, 0, 0, 0] ]) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu']) t = ''.join([t0, 'DC PF (with DC lines) : ']) ppc1 = {'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()} ppc1 = toggle_dcline(ppc1, 'on') ppc1['bus'][:, VA] = 0 rp = rundcpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage']) t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow']) ## add appropriate P injections and check angles and generation when running PF t = ''.join([t0, 'DC PF (with equivalent injections) : ']) ppc1 = {'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()} ppc1['bus'][:, VA] = 0 for k in range(ndc): if ppc1['dcline'][k, c.BR_STATUS]: ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS]) tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS]) ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF] ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT] ppc1['bus'][ff, BUS_TYPE] = PV ppc1['bus'][tt, BUS_TYPE] = PV rp = rundcpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage']) t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow']) ## run with DC lines t = ''.join([t0, 'AC OPF (with DC lines + poly cost) : ']) ppc = loadcase(casefile) ppc = toggle_dcline(ppc, 'on') r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) expected1 = array([ [10, 8.9, -10, 10, 1.0663, 1.0936], [7.8429, 7.8429, 0, 0, 1.0809, 1.0667], [0, 0, 0, 0, 1.0000, 1.0000], [6.0549, 5.7522, -0.5897, -10, 1.0778, 1.0667] ]) t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V']) expected2 = array([ [0, 0.7605, 0.6226, 0, 0, 0.2980], [0, 0, 0, 0.4275, 0.0792, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0.0792, 0] ]) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu']) ppc['dclinecost'][3, :8] = array([2, 0, 0, 4, 0, 0, 7.3, 0]) r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V']) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu']) t = ''.join([t0, 'AC OPF (with DC lines + pwl cost) : ']) ppc['dclinecost'][3, :8] = array([1, 0, 0, 2, 0, 0, 10, 73]) r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V']) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu']) t_end()
def t_pf(quiet=False): """Tests for power flow solvers. @author: Ray Zimmerman (PSERC Cornell) """ t_begin(33, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_pf') verbose = not quiet ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] ## run Newton PF t = 'Newton PF : ' ppopt = ppoption(ppopt, PF_ALG=1) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (XB version) t = 'Fast Decoupled (XB) PF : ' ppopt = ppoption(ppopt, PF_ALG=2) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (BX version) t = 'Fast Decoupled (BX) PF : ' ppopt = ppoption(ppopt, PF_ALG=3) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run Gauss-Seidel PF t = 'Gauss-Seidel PF : ' ppopt = ppoption(ppopt, PF_ALG=4) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 5, [t, 'bus']) t_is(gen, gen_soln, 5, [t, 'gen']) t_is(branch, branch_soln, 5, [t, 'branch']) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_dcpf = loadmat(join(tdir, 'soln9_dcpf.mat'), struct_as_record=False) bus_soln = soln9_dcpf['bus_soln'] gen_soln = soln9_dcpf['gen_soln'] branch_soln = soln9_dcpf['branch_soln'] ## run DC PF t = 'DC PF : ' results, success = rundcpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## check Qg distribution, when Qmin = Qmax t = 'check Qg : ' ppopt = ppoption(ppopt, PF_ALG=1, VERBOSE=0) ppc = loadcase(casefile) ppc['gen'][0, [QMIN, QMAX]] = [20, 20] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0, QG], 24.07, 2, [t, 'single gen, Qmin = Qmax']) ppc['gen'] = r_[array([ppc['gen'][0, :]]), ppc['gen']] ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [0, 50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [10, 14.07], 2, [t, '2 gens, Qmin = Qmax for one']) ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [-50, -50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [12.03, 12.03], 2, [t, '2 gens, Qmin = Qmax for both']) ppc['gen'][0, [QMIN, QMAX]] = [0, 50] ppc['gen'][1, [QMIN, QMAX]] = [0, 100] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [8.02, 16.05], 2, [t, '2 gens, proportional']) ppc['gen'][0, [QMIN, QMAX]] = [-50, 0] ppc['gen'][1, [QMIN, QMAX]] = [50, 150] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [-50 + 8.02, 50 + 16.05], 2, [t, '2 gens, proportional']) ## network with islands t = 'network w/islands : DC PF : ' ppc0 = loadcase(casefile) ppc0['gen'][0, PG] = 60 ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] = \ ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] / 2 ppc0['gen'] = r_[array([ppc0['gen'][0, :]]), ppc0['gen']] ppc1 = ppc0.copy() ppc = ppc0.copy() nb = ppc['bus'].shape[0] ppc1['bus'][:, BUS_I] = ppc1['bus'][:, BUS_I] + nb ppc1['branch'][:, F_BUS] = ppc1['branch'][:, F_BUS] + nb ppc1['branch'][:, T_BUS] = ppc1['branch'][:, T_BUS] + nb ppc1['gen'][:, GEN_BUS] = ppc1['gen'][:, GEN_BUS] + nb ppc['bus'] = r_[ppc['bus'], ppc1['bus']] ppc['branch'] = r_[ppc['branch'], ppc1['branch']] ppc['gen'] = r_[ppc['gen'], ppc1['gen']] #ppopt = ppoption(ppopt, OUT_BUS=1, OUT_GEN=1, OUT_ALL=-1, VERBOSE=2) ppopt = ppoption(ppopt, VERBOSE=verbose) r = rundcpf(ppc, ppopt) t_is(r['bus'][:9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][10:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][:4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t = 'network w/islands : AC PF : ' ## get solved AC power flow case from MAT-file soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] r = runpf(ppc, ppopt) t_is(r['bus'][:9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][9:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][:4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t_end()
def t_loadcase(quiet=False): """Test that C{loadcase} works with an object as well as case file. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ t_begin(240, quiet) ## compare result of loading from M-file file to result of using data matrices tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') matfile = join(tdir, 't_mat9_opf') pfcasefile = join(tdir, 't_case9_pf') pfmatfile = join(tdir, 't_mat9_pf') casefilev2 = join(tdir, 't_case9_opfv2') matfilev2 = join(tdir, 't_mat9_opfv2') pfcasefilev2 = join(tdir, 't_case9_pfv2') pfmatfilev2 = join(tdir, 't_mat9_pfv2') ## read version 1 OPF data matrices baseMVA, bus, gen, branch, areas, gencost = t_case9_opf() ## save as .mat file savemat(matfile + '.mat', {'baseMVA': baseMVA, 'bus': bus, 'gen': gen, 'branch': branch, 'areas': areas, 'gencost': gencost}, oned_as='row') ## read version 2 OPF data matrices ppc = t_case9_opfv2() ## save as .mat file savemat(matfilev2 + '.mat', {'ppc': ppc}, oned_as='column') ## prepare expected matrices for v1 load ## (missing gen cap curve & branch ang diff lims) tmp1 = (ppc['baseMVA'], ppc['bus'].copy(), ppc['gen'].copy(), ppc['branch'].copy(), ppc['areas'].copy(), ppc['gencost'].copy()) tmp2 = (ppc['baseMVA'], ppc['bus'].copy(), ppc['gen'].copy(), ppc['branch'].copy(), ppc['areas'].copy(), ppc['gencost'].copy()) ## remove capability curves, angle difference limits tmp1[2][1:3, [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX]] = zeros((2,6)) tmp1[3][0, ANGMAX] = 360 tmp1[3][8, ANGMIN] = -360 baseMVA, bus, gen, branch, areas, gencost = tmp1 ##----- load OPF data into individual matrices ----- t = 'loadcase(opf_PY_file_v1) without .py extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(casefile, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_PY_file_v1) with .py extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(casefile + '.py', False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_MAT_file_v1) without .mat extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(matfile, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_MAT_file_v1) with .mat extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(matfile + '.mat', False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) ## prepare expected matrices for v2 load baseMVA, bus, gen, branch, areas, gencost = tmp2 t = 'loadcase(opf_PY_file_v2) without .py extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(casefilev2, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_PY_file_v2) with .py extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(casefilev2 + '.py', False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_MAT_file_v2) without .mat extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(matfilev2, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_MAT_file_v2) with .mat extension : ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = \ loadcase(matfilev2 + '.mat', False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t_is(areas1, areas, 12, [t, 'areas']) t_is(gencost1, gencost, 12, [t, 'gencost']) ## prepare expected matrices for v1 load baseMVA, bus, gen, branch, areas, gencost = tmp1 t = 'loadcase(opf_struct_v1) (no version): ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = t_case9_opf() c = {} c['baseMVA'] = baseMVA1 c['bus'] = bus1.copy() c['gen'] = gen1.copy() c['branch'] = branch1.copy() c['areas'] = areas1.copy() c['gencost'] = gencost1.copy() baseMVA2, bus2, gen2, branch2, areas2, gencost2 = loadcase(c, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) t_is(areas2, areas, 12, [t, 'areas']) t_is(gencost2, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_struct_v1) (version=\'1\'): ' c['version'] = '1' baseMVA2, bus2, gen2, branch2, areas2, gencost2 = loadcase(c, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) t_is(areas2, areas, 12, [t, 'areas']) t_is(gencost2, gencost, 12, [t, 'gencost']) ## prepare expected matrices for v2 load baseMVA, bus, gen, branch, areas, gencost = tmp2 t = 'loadcase(opf_struct_v2) (no version): ' c = {} c['baseMVA'] = baseMVA c['bus'] = bus.copy() c['gen'] = gen.copy() c['branch'] = branch.copy() c['areas'] = areas.copy() c['gencost'] = gencost.copy() baseMVA2, bus2, gen2, branch2, areas2, gencost2 = loadcase(c, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) t_is(areas2, areas, 12, [t, 'areas']) t_is(gencost2, gencost, 12, [t, 'gencost']) t = 'loadcase(opf_struct_v2) (version=''2''): ' c = {} c['baseMVA'] = baseMVA c['bus'] = bus.copy() c['gen'] = gen.copy() c['branch'] = branch.copy() c['areas'] = areas.copy() c['gencost'] = gencost.copy() c['version'] = '2' baseMVA2, bus2, gen2, branch2, areas2, gencost2 = loadcase(c, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) t_is(areas2, areas, 12, [t, 'areas']) t_is(gencost2, gencost, 12, [t, 'gencost']) ##----- load OPF data into struct ----- ## prepare expected matrices for v1 load baseMVA, bus, gen, branch, areas, gencost = tmp1 t = 'ppc = loadcase(opf_PY_file_v1) without .py extension : ' ppc1 = loadcase(casefile) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_PY_file_v1) with .py extension : ' ppc1 = loadcase(casefile + '.py') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_MAT_file_v1) without .mat extension : ' ppc1 = loadcase(matfile) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_MAT_file_v1) with .mat extension : ' ppc1 = loadcase(matfile + '.mat') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) ## prepare expected matrices for v2 load baseMVA, bus, gen, branch, areas, gencost = tmp2 t = 'ppc = loadcase(opf_PY_file_v2) without .m extension : ' ppc1 = loadcase(casefilev2) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_PY_file_v2) with .py extension : ' ppc1 = loadcase(casefilev2 + '.py') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_MAT_file_v2) without .mat extension : ' ppc1 = loadcase(matfilev2) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_MAT_file_v2) with .mat extension : ' ppc1 = loadcase(matfilev2 + '.mat') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t_is(ppc1['areas'], areas, 12, [t, 'areas']) t_is(ppc1['gencost'], gencost, 12, [t, 'gencost']) ## prepare expected matrices for v1 load baseMVA, bus, gen, branch, areas, gencost = tmp1 t = 'ppc = loadcase(opf_struct_v1) (no version): ' baseMVA1, bus1, gen1, branch1, areas1, gencost1 = t_case9_opf() c = {} c['baseMVA'] = baseMVA1 c['bus'] = bus1.copy() c['gen'] = gen1.copy() c['branch'] = branch1.copy() c['areas'] = areas1.copy() c['gencost'] = gencost1.copy() ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) t_is(ppc2['areas'], areas, 12, [t, 'areas']) t_is(ppc2['gencost'], gencost, 12, [t, 'gencost']) t = 'ppc = loadcase(opf_struct_v1) (version=''1''): ' c['version'] = '1' ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) t_is(ppc2['areas'], areas, 12, [t, 'areas']) t_is(ppc2['gencost'], gencost, 12, [t, 'gencost']) ## prepare expected matrices for v2 load baseMVA, bus, gen, branch, areas, gencost = tmp2 t = 'ppc = loadcase(opf_struct_v2) (no version): ' c = {} c['baseMVA'] = baseMVA c['bus'] = bus.copy() c['gen'] = gen.copy() c['branch'] = branch.copy() c['areas'] = areas.copy() c['gencost'] = gencost.copy() ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) t_is(ppc2['areas'], areas, 12, [t, 'areas']) t_is(ppc2['gencost'], gencost, 12, [t, 'gencost']) t_ok(ppc2['version'] == '2', [t, 'version']) t = 'ppc = loadcase(opf_struct_v2) (version=''2''): ' c = {} c['baseMVA'] = baseMVA c['bus'] = bus.copy() c['gen'] = gen.copy() c['branch'] = branch.copy() c['areas'] = areas.copy() c['gencost'] = gencost.copy() c['version'] = '2' ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) t_is(ppc2['areas'], areas, 12, [t, 'areas']) t_is(ppc2['gencost'], gencost, 12, [t, 'gencost']) ## read version 1 PF data matrices baseMVA, bus, gen, branch = t_case9_pf() savemat(pfmatfile + '.mat', {'baseMVA': baseMVA, 'bus': bus, 'gen': gen, 'branch': branch}, oned_as='column') ## read version 2 PF data matrices ppc = t_case9_pfv2() tmp = (ppc['baseMVA'], ppc['bus'].copy(), ppc['gen'].copy(), ppc['branch'].copy()) baseMVA, bus, gen, branch = tmp ## save as .mat file savemat(pfmatfilev2 + '.mat', {'ppc': ppc}, oned_as='column') ##----- load PF data into individual matrices ----- t = 'loadcase(pf_PY_file_v1) without .py extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfcasefile, False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_PY_file_v1) with .py extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfcasefile + '.py', False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_MAT_file_v1) without .mat extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfmatfile, False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_MAT_file_v1) with .mat extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfmatfile + '.mat', False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_PY_file_v2) without .py extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfcasefilev2, False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_PY_file_v2) with .py extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfcasefilev2 + '.py', False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_MAT_file_v2) without .mat extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfmatfilev2, False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_MAT_file_v2) with .mat extension : ' baseMVA1, bus1, gen1, branch1 = \ loadcase(pfmatfilev2 + '.mat', False, False, False) t_is(baseMVA1, baseMVA, 12, [t, 'baseMVA']) t_is(bus1, bus, 12, [t, 'bus']) t_is(gen1, gen, 12, [t, 'gen']) t_is(branch1, branch, 12, [t, 'branch']) t = 'loadcase(pf_struct_v1) (no version): ' baseMVA1, bus1, gen1, branch1 = t_case9_pf() c = {} c['baseMVA'] = baseMVA1 c['bus'] = bus1.copy() c['gen'] = gen1.copy() c['branch'] = branch1.copy() baseMVA2, bus2, gen2, branch2 = loadcase(c, False, False, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) t = 'loadcase(pf_struct_v1) (version=''1''): ' c['version'] = '1' baseMVA2, bus2, gen2, branch2 = loadcase(c, False, False, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) t = 'loadcase(pf_struct_v2) : ' c = {} c['baseMVA'] = baseMVA c['bus'] = bus.copy() c['gen'] = gen.copy() c['branch'] = branch.copy() c['version'] = '2' baseMVA2, bus2, gen2, branch2 = loadcase(c, False, False, False) t_is(baseMVA2, baseMVA, 12, [t, 'baseMVA']) t_is(bus2, bus, 12, [t, 'bus']) t_is(gen2, gen, 12, [t, 'gen']) t_is(branch2, branch, 12, [t, 'branch']) ##----- load PF data into struct ----- t = 'ppc = loadcase(pf_PY_file_v1) without .py extension : ' ppc1 = loadcase(pfcasefile) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_PY_file_v1) with .py extension : ' ppc1 = loadcase(pfcasefile + '.py') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_MAT_file_v1) without .mat extension : ' ppc1 = loadcase(pfmatfile) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_MAT_file_v1) with .mat extension : ' ppc1 = loadcase(pfmatfile + '.mat') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_PY_file_v2) without .py extension : ' ppc1 = loadcase(pfcasefilev2) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_PY_file_v2) with .py extension : ' ppc1 = loadcase(pfcasefilev2 + '.py') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_MAT_file_v2) without .mat extension : ' ppc1 = loadcase(pfmatfilev2) t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_MAT_file_v2) with .mat extension : ' ppc1 = loadcase(pfmatfilev2 + '.mat') t_is(ppc1['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc1['bus'], bus, 12, [t, 'bus']) t_is(ppc1['gen'], gen, 12, [t, 'gen']) t_is(ppc1['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_struct_v1) (no version): ' baseMVA1, bus1, gen1, branch1 = t_case9_pf() c = {} c['baseMVA'] = baseMVA1 c['bus'] = bus1.copy() c['gen'] = gen1.copy() c['branch'] = branch1.copy() ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_struct_v1) (version=''1''): ' c['version'] = '1' ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) t = 'ppc = loadcase(pf_struct_v2) : ' c = {} c['baseMVA'] = baseMVA c['bus'] = bus.copy() c['gen'] = gen.copy() c['branch'] = branch.copy() c['version'] = '2' ppc2 = loadcase(c) t_is(ppc2['baseMVA'], baseMVA, 12, [t, 'baseMVA']) t_is(ppc2['bus'], bus, 12, [t, 'bus']) t_is(ppc2['gen'], gen, 12, [t, 'gen']) t_is(ppc2['branch'], branch, 12, [t, 'branch']) ## cleanup os.remove(matfile + '.mat') os.remove(pfmatfile + '.mat') os.remove(matfilev2 + '.mat') os.remove(pfmatfilev2 + '.mat') t = 'runpf(my_PY_file)' ppopt = ppoption(VERBOSE=0, OUT_ALL=0) results3, success = runpf(pfcasefile, ppopt) baseMVA3, bus3, gen3, branch3 = results3['baseMVA'], results3['bus'], \ results3['gen'], results3['branch'] t_ok( success, t ) t = 'runpf(my_object)' results4, success = runpf(c, ppopt) baseMVA4, bus4, gen4, branch4 = results4['baseMVA'], results4['bus'], \ results4['gen'], results4['branch'] t_ok( success, t ) t = 'runpf result comparison : ' t_is(baseMVA3, baseMVA4, 12, [t, 'baseMVA']) t_is(bus3, bus4, 12, [t, 'bus']) t_is(gen3, gen4, 12, [t, 'gen']) t_is(branch3, branch4, 12, [t, 'branch']) t = 'runpf(modified_struct)' c['gen'][2, 1] = c['gen'][2, 1] + 1 ## increase gen 3 output by 1 results5, success = runpf(c, ppopt) gen5 = results5['gen'] t_is(gen5[0, 1], gen4[0, 1] - 1, 1, t) ## slack bus output should decrease by 1 t_end()
def t_opf_dc_pips_sc(quiet=False): """Tests for DC optimal power flow using PIPS-sc solver. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ num_tests = 23 t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') verbose = 0 #not quiet t0 = 'DC OPF (PIPS-sc): ' ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0, OPF_ALG_DC=250) ## run DC OPF ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) #ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## get solved DC power flow case from MAT-file soln9_dcopf = loadmat(join(tdir, 'soln9_dcopf.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_dcopf['bus_soln'] gen_soln = soln9_dcopf['gen_soln'] branch_soln = soln9_dcopf['branch_soln'] f_soln = soln9_dcopf['f_soln'][0] ## run OPF t = t0 r = rundcopf(casefile, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is(bus[:, ib_data], bus_soln[:, ib_data], 10, [t, 'bus data']) t_is(bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is(bus[:, ib_lam], bus_soln[:, ib_lam], 3, [t, 'bus lambda']) t_is(bus[:, ib_mu], bus_soln[:, ib_mu], 2, [t, 'bus mu']) t_is(gen[:, ig_data], gen_soln[:, ig_data], 10, [t, 'gen data']) t_is(gen[:, ig_disp], gen_soln[:, ig_disp], 3, [t, 'gen dispatch']) t_is(gen[:, ig_mu], gen_soln[:, ig_mu], 3, [t, 'gen mu']) t_is(branch[:, ibr_data], branch_soln[:, ibr_data], 10, [t, 'branch data']) t_is(branch[:, ibr_flow], branch_soln[:, ibr_flow], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu], branch_soln[:, ibr_mu], 2, [t, 'branch mu']) ##----- run OPF with extra linear user constraints & costs ----- ## two new z variables ## 0 <= z1, P2 - P1 <= z1 ## 0 <= z2, P2 - P3 <= z2 ## with A and N sized for DC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [9, 10, 12, 10, 11, 13] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 14)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [12, 13])), (2, 14)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 1 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) ## with A and N sized for AC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [18, 19, 24, 19, 20, 25] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 26)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [24, 25])), (2, 26)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 2 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) t = ''.join([t0, 'infeasible : ']) ## with A and N sized for DC opf ppc = loadcase(casefile) ppc['A'] = sparse(([1, 1], ([0, 0], [9, 10])), (1, 14)) ## Pg1 + Pg2 ppc['u'] = array([Inf]) ppc['l'] = array([600]) r = rundcopf(ppc, ppopt) t_ok(not r['success'], [t, 'no success']) t_end()
def t_savecase(quiet=False): """Tests that C{savecase} saves case files in MAT and PY file formats.""" t_begin(12, quiet) MATCASE = 'test_savedcase.mat' PYCASE = 'test_savedcase.py' file_formats = [MATCASE, PYCASE] pf_case = {'case': case24_ieee_rts(), 'run_func': runpf, 'run_label': 'PF run'} opf_case = {'case': case24_ieee_rts(), 'run_func': runopf, 'run_label': 'OPF run'} case_unsolved = {'case': case24_ieee_rts(), 'run_func': None, 'run_label': 'pre-run'} cases = [pf_case, opf_case, case_unsolved] tmpdir = tempfile.mkdtemp() for case in cases: for i, filename in enumerate([f for f in file_formats]): file_format = save_format(filename) # 'mat' or 'py' saved_umask = os.umask(0o22) path = join(tmpdir, filename) ppc = case['case'] pf_func = case['run_func'] run_type = case['run_label'] # Test saving of results if case has been solved if pf_func: ppopt = ppoption(VERBOSE=0, OUT_ALL=0) # Run power flow type specified, assign solution to case ppc = pf_func(ppc, ppopt) # runpf.py returns a tuple containing the result if isinstance(ppc, tuple): ppc = ppc[0] try: savedcase = savecase(path, ppc, comment=None, version='2') except IOError: t_ok(False, ['Savecase: ', 'IOError.']) else: # Do tests msg_prefix = message_prefix(file_format, run_type) loaded_case = loadcase(savedcase) msg_desc = ' file name matches argument' t_ok(savedcase == path, msg_prefix + msg_desc) msg_desc = ' file content matches case' # Boolean: saved key-value pairs do/do not correspond to case saved_case_matches_ppc = verify_saved_case(loaded_case, ppc) t_ok(saved_case_matches_ppc, msg_prefix + msg_desc) os.remove(path) finally: os.umask(saved_umask) os.rmdir(tmpdir)
def t_scale_load(quiet=False): """Tests for code in C{scale_load}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ n_tests = 275 t_begin(n_tests, quiet) ppc = loadcase(join(dirname(__file__), 't_auction_case')) ppc['gen'][7, GEN_BUS] = 2 ## multiple d. loads per area, same bus as gen ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3]) ## put it load before gen in matrix ppc['gen'] = vstack([ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]]) ld = find(isload(ppc['gen'])) a = [None] * 3 lda = [None] * 3 for k in range(3): a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1) ## buses in area k tmp = find( in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k]) ) lda[k] = ld[tmp] ## disp loads in area k area = [None] * 3 for k in range(3): area[k] = {'fixed': {}, 'disp': {}, 'both': {}} area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD]) area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD]) area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN]) area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN]) area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX]) area[k]['disp']['q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax'] area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p'] area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q'] total = {'fixed': {}, 'disp': {}, 'both': {}} total['fixed']['p'] = sum(ppc['bus'][:, PD]) total['fixed']['q'] = sum(ppc['bus'][:, QD]) total['disp']['p'] = -sum(ppc['gen'][ld, PMIN]) total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN]) total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX]) total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax'] total['both']['p'] = total['fixed']['p'] + total['disp']['p'] total['both']['q'] = total['fixed']['q'] + total['disp']['q'] ##----- single load zone, one scale factor ----- load = array([2]) t = 'all fixed loads (PQ) * 2 : ' bus, _ = scale_load(load, ppc['bus']) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all fixed loads (P) * 2 : ' opt = {'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (PQ) * 2 : ' bus, gen = scale_load(load, ppc['bus'], ppc['gen']) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), load * total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), load * total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (P) * 2 : ' opt = {'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (PQ) * 2 : ' opt = {'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), load * total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), load * total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (P) * 2 : ' opt = {'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) ##----- single load zone, one scale quantity ----- load = array([200.0]) t = 'all fixed loads (PQ) => total = 200 : ' opt = {'scale': 'QUANTITY'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) t_is(sum(bus[:, PD]), load, 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load / total['fixed']['p'] * total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'scale': 'QUANTITY', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load - total['disp']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), (load - total['disp']['p'])/total['fixed']['p']*total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all fixed loads (P) => total = 200 : ' opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) t_is(sum(bus[:, PD]), load, 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load - total['disp']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (PQ) => total = 200 : ' opt = {'scale': 'QUANTITY'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load / total['both']['p']*total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), load / total['both']['p']*total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load / total['both']['p']*total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), load / total['both']['p']*total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), load / total['both']['p']*total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all loads (P) => total = 200 : ' opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), load / total['both']['p']*total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load / total['both']['p']*total['disp']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (PQ) => total = 200 : ' opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load - total['fixed']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), (load - total['fixed']['p'])/total['disp']['p']*total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), (load - total['fixed']['p'])/total['disp']['p']*total['disp']['qmax'], 8, [t, 'total disp Qmax']) t = 'all disp loads (P) => total = 200 : ' opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P']) t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q']) t_is(-sum(gen[ld, PMIN]), load - total['fixed']['p'], 8, [t, 'total disp P']) t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin']) t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax']) ##----- 3 zones, area scale factors ----- t = 'area fixed loads (PQ) * [3 2 1] : ' load = array([3, 2, 1]) bus, _ = scale_load(load, ppc['bus']) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area fixed loads (P) * [3 2 1] : ' load = array([3, 2, 1]) opt = {'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (PQ) * [3 2 1] : ' bus, gen = scale_load(load, ppc['bus'], ppc['gen']) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), load[k] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), load[k] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (P) * [3 2 1] : ' opt = {'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (PQ) * [3 2 1] : ' opt = {'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), load[k] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), load[k] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (P) * [3 2 1] : ' opt = {'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) ##----- 3 zones, area scale quantities ----- t = 'area fixed loads (PQ) => total = [100 80 60] : ' load = array([100, 80, 60], float) opt = {'scale': 'QUANTITY'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] / area[k]['fixed']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'scale': 'QUANTITY', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] - area[k]['disp']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), (load[k] - area[k]['disp']['p']) / area[k]['fixed']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area fixed loads (P) => total = [100 80 60] : ' load = array([100, 80, 60], float) opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, _ = scale_load(load, ppc['bus'], None, None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'FIXED'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k]-area[k]['disp']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (PQ) => total = [100 80 60] : ' opt = {'scale': 'QUANTITY'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), load[k] / area[k]['both']['p'] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'all area loads (P) => total = [100 80 60] : ' opt = {'scale': 'QUANTITY', 'pq': 'P'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (PQ) => total = [100 80 60] : throws expected exception' load = array([100, 80, 60], float) opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'} err = 0 try: bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) except ScalingError as e: expected = 'scale_load: impossible to make zone 2 load equal 80 by scaling non-existent dispatchable load' err = expected not in str(e) t_ok(err, t) t = 'area disp loads (PQ) => total = [100 74.3941 60] : ' load = array([100, area[1]['fixed']['p'], 60], float) opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k]-area[k]['fixed']['p'], 8, '%s area %d disp P' % (t, k)) if k == 1: t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) else: t_is(-sum(gen[lda[k], QMIN]), (load[k] - area[k]['fixed']['p']) / area[k]['disp']['p'] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), (load[k] - area[k]['fixed']['p']) / area[k]['disp']['p'] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) t = 'area disp loads (P) => total = [100 74.3941 60] : ' opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'DISPATCHABLE'} bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt) for k in range(len(load)): t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k)) t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k)) t_is(-sum(gen[lda[k], PMIN]), load[k]-area[k]['fixed']['p'], 8, '%s area %d disp P' % (t, k)) t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k)) t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k)) ##----- explict single load zone ----- t = 'explicit single load zone' load_zone = zeros(ppc['bus'].shape[0]) load_zone[[2, 3]] = 1 load = array([2.0]) bus, gen = scale_load(load, ppc['bus'], ppc['gen'], load_zone) Pd = ppc['bus'][:, PD] Pd[[2, 3]] = load * Pd[[2, 3]] t_is( bus[:, PD], Pd, 8, t) ##----- explict multiple load zone ----- t = 'explicit multiple load zone' load_zone = zeros(ppc['bus'].shape[0]) load_zone[[2, 3]] = 1 load_zone[[6, 7]] = 2 load = array([2, 0.5]) bus, gen = scale_load(load, ppc['bus'], ppc['gen'], load_zone) Pd = ppc['bus'][:, PD] Pd[[2, 3]] = load[0] * Pd[[2, 3]] Pd[[6, 7]] = load[1] * Pd[[6, 7]] t_is( bus[:, PD], Pd, 8, t) t_end()
def t_opf_dc_gurobi(quiet=False): """Tests for DC optimal power flow using Gurobi solver. """ algs = [0, 1, 2, 3, 4] num_tests = 23 * len(algs) t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') if quiet: verbose = False else: verbose = False ppopt = ppoption('OUT_ALL', 0, 'VERBOSE', verbose) ppopt = ppoption(ppopt, 'OPF_ALG_DC', 700) ## run DC OPF if have_fcn('gurobipy'): for k in range(len(algs)): ppopt = ppoption(ppopt, 'GRB_METHOD', algs[k]) methods = [ 'automatic', 'primal simplex', 'dual simplex', 'barrier', 'concurrent', 'deterministic concurrent', ] t0 = 'DC OPF (Gurobi %s): ' % methods[k] ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) #ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## get solved DC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln, f_soln soln9_dcopf = loadmat(join(tdir, 'soln9_dcopf.mat'), struct_as_record=True) bus_soln, gen_soln, branch_soln, f_soln = \ soln9_dcopf['bus_soln'], soln9_dcopf['gen_soln'], \ soln9_dcopf['branch_soln'], soln9_dcopf['f_soln'] ## run OPF t = t0 r = rundcopf(casefile, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is(bus[:, ib_data], bus_soln[:, ib_data], 10, [t, 'bus data']) t_is(bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is(bus[:, ib_lam], bus_soln[:, ib_lam], 3, [t, 'bus lambda']) t_is(bus[:, ib_mu], bus_soln[:, ib_mu], 2, [t, 'bus mu']) t_is(gen[:, ig_data], gen_soln[:, ig_data], 10, [t, 'gen data']) t_is(gen[:, ig_disp], gen_soln[:, ig_disp], 3, [t, 'gen dispatch']) t_is(gen[:, ig_mu], gen_soln[:, ig_mu], 3, [t, 'gen mu']) t_is(branch[:, ibr_data], branch_soln[:, ibr_data], 10, [t, 'branch data']) t_is(branch[:, ibr_flow], branch_soln[:, ibr_flow], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu], branch_soln[:, ibr_mu], 2, [t, 'branch mu']) ##----- run OPF with extra linear user constraints & costs ----- ## two new z variables ## 0 <= z1, P2 - P1 <= z1 ## 0 <= z2, P2 - P3 <= z2 ## with A and N sized for DC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [9, 10, 12, 10, 11, 13] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 14)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [12, 13])), (2, 14)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 1 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) ## with A and N sized for AC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [18, 19, 24, 19, 20, 25] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 26)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [24, 25])), (2, 26)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 2 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) t = ''.join([t0, 'infeasible : ']) ## with A and N sized for DC opf ppc = loadcase(casefile) ppc['A'] = sparse(([1, 1], ([0, 0], [9, 10])), (1, 14)) ## Pg1 + Pg2 ppc['u'] = array([Inf]) ppc['l'] = array([600]) r = rundcopf(ppc, ppopt) t_ok(not r['success'], [t, 'no success']) else: t_skip(num_tests, 'Gurobi not available') t_end()
def t_runopf_w_res(quiet=False): """Tests C{runopf_w_res} and the associated callbacks. @author: Ray Zimmerman (PSERC Cornell) """ t_begin(46, quiet) verbose = 0 #not quiet tdir = dirname(__file__) casefile = join(tdir, 't_case30_userfcns') ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=560) t = 'runopf_w_res(' 't_case30_userfcns' ') : ' r = runopf_w_res(casefile, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 7, [t, 'mu.Pmax']) ppc = loadcase(casefile) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t = 'gen 5 no reserves : ' ppc = loadcase(casefile) ppc['reserves']['zones'][:, 4] = 0 ppc['reserves']['cost'] = delete(ppc['reserves']['cost'], 4) ppc['reserves']['qty'] = delete(ppc['reserves']['qty'], 4) r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 0, 20], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 0, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 6, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 187.5, 4, [t, 'totalcost']) t = 'extra offline gen : ' ppc = loadcase(casefile) idx = list(range(3)) + [4] + list(range(3, 6)) ppc['gen'] = ppc['gen'][idx, :] ppc['gencost'] = ppc['gencost'][idx, :] ppc['reserves']['zones'] = ppc['reserves']['zones'][:, idx] ppc['reserves']['cost'] = ppc['reserves']['cost'][idx] ppc['reserves']['qty'] = ppc['reserves']['qty'][idx] ppc['gen'][3, GEN_STATUS] = 0 r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 0, 19.3906, 0.6094], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 5.5, 2, 5.5, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 0, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0, 0.5, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t = 'both extra & gen 6 no res : ' ppc = loadcase(casefile) idx = list(range(3)) + [4] + list(range(3, 6)) ppc['gen'] = ppc['gen'][idx, :] ppc['gencost'] = ppc['gencost'][idx, :] ppc['reserves']['zones'] = ppc['reserves']['zones'][:, idx] ppc['reserves']['cost'] = ppc['reserves']['cost'][idx] ppc['reserves']['qty'] = ppc['reserves']['qty'][idx] ppc['gen'][3, GEN_STATUS] = 0 ppc['reserves']['zones'][:, 5] = 0 ppc['reserves']['cost'] = delete(ppc['reserves']['cost'], 5) ppc['reserves']['qty'] = delete(ppc['reserves']['qty'], 5) r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 0, 0, 20], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 5.5, 2, 0, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 0, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0, 0], 6, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0, 0, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['qty'], ppc['reserves']['qty'], 12, [t, 'qty']) t_is(r['reserves']['totalcost'], 187.5, 4, [t, 'totalcost']) t = 'no qty (Rmax) : ' ppc = loadcase(casefile) del ppc['reserves']['qty'] r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [39.3826, 0.6174, 0, 0, 19.3818, 0.6182], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 5, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 5, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0.1, 0, 0, 0, 0.5, 0], 5, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['totalcost'], 176.3708, 4, [t, 'totalcost']) t = 'RAMP_10, no qty (Rmax) : ' ppc = loadcase(casefile) del ppc['reserves']['qty'] ppc['gen'][0, RAMP_10] = 25 r = runopf_w_res(ppc, ppopt) t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 6, [t, 'prc']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 7, [t, 'mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 7, [t, 'mu.u']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 7, [t, 'mu.Pmax']) t_is(r['reserves']['cost'], ppc['reserves']['cost'], 12, [t, 'cost']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t_end()
from pypower.loadcase import loadcase import matplotlib.pyplot as plt import numpy as np if __name__ == '__main__': ######### # SETUP # ######### print('---------------------------------------') print('PYPOWER-Dynamics - 9 Bus Stability Test') print('---------------------------------------') # Load PYPOWER case ppc = loadcase('case9.py') # Program options dynopt = {} dynopt['h'] = 0.01 # step length (s) dynopt['t_sim'] = 5.0 # simulation time (s) dynopt[ 'max_err'] = 1e-6 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 60 # Nominal system frequency (Hz) dynopt[ 'speed_volt'] = True # Speed-voltage term option (for current injection calculation) # Integrator option #dynopt['iopt'] = 'mod_euler'
from pypower.loadcase import loadcase import matplotlib.pyplot as plt import numpy as np if __name__ == '__main__': ######### # SETUP # ######### print('---------------------------------------') print('PYPOWER-Dynamics - 9 Bus Stability Test') print('---------------------------------------') # Load PYPOWER case ppc = loadcase('case9.py') # Program options dynopt = {} dynopt['h'] = 0.01 # step length (s) dynopt['t_sim'] = 5.0 # simulation time (s) dynopt['max_err'] = 1e-6 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 60 # Nominal system frequency (Hz) dynopt['speed_volt'] = True # Speed-voltage term option (for current injection calculation) # Integrator option #dynopt['iopt'] = 'mod_euler' dynopt['iopt'] = 'runge_kutta'
if __name__ == "__main__": from unit_commitment.test_cases import case118 test_case = case118.case118() from pypower.case118 import case118 from pypower.idx_brch import F_BUS, T_BUS, BR_X, TAP, SHIFT, BR_STATUS, RATE_A from pypower.idx_cost import MODEL, NCOST, PW_LINEAR, COST, POLYNOMIAL from pypower.idx_bus import BUS_TYPE, REF, VA, VM, PD, GS, VMAX, VMIN, BUS_I from pypower.idx_gen import GEN_BUS, VG, PG, QG, PMAX, PMIN, QMAX, QMIN from numpy import flatnonzero as find casedata = case118() mpc = loadcase.loadcase(casedata) mpc = ext2int.ext2int(mpc) baseMVA, bus, gen, branch, gencost = mpc["baseMVA"], mpc["bus"], mpc[ "gen"], mpc["branch"], mpc["gencost"] # nb = shape(mpc['bus'])[0] ## number of buses nl = shape(mpc['branch'])[0] ## number of branches ng = shape(mpc['gen'])[0] ## number of dispatchable injections ## Formualte the stat = branch[:, BR_STATUS] ## ones at in-service branches b = stat / branch[:, BR_X] ## series susceptance tap = ones(nl) ## default tap ratio = 1 i = find(branch[:, TAP]) ## indices of non-zero tap ratios tap[i] = branch[i, TAP] ## assign non-zero tap ratios
def t_opf_dc_gurobi(quiet=False): """Tests for DC optimal power flow using Gurobi solver. """ algs = [0, 1, 2, 3, 4] num_tests = 23 * len(algs) t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') if quiet: verbose = False else: verbose = False ppopt = ppoption('OUT_ALL', 0, 'VERBOSE', verbose); ppopt = ppoption(ppopt, 'OPF_ALG_DC', 700); ## run DC OPF if have_fcn('gurobipy'): for k in range(len(algs)): ppopt = ppoption(ppopt, 'GRB_METHOD', algs[k]) methods = [ 'automatic', 'primal simplex', 'dual simplex', 'barrier', 'concurrent', 'deterministic concurrent', ] t0 = 'DC OPF (Gurobi %s): ' % methods[k] ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) #ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## get solved DC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln, f_soln soln9_dcopf = loadmat(join(tdir, 'soln9_dcopf.mat'), struct_as_record=True) bus_soln, gen_soln, branch_soln, f_soln = \ soln9_dcopf['bus_soln'], soln9_dcopf['gen_soln'], \ soln9_dcopf['branch_soln'], soln9_dcopf['f_soln'] ## run OPF t = t0 r = rundcopf(casefile, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ##----- run OPF with extra linear user constraints & costs ----- ## two new z variables ## 0 <= z1, P2 - P1 <= z1 ## 0 <= z2, P2 - P3 <= z2 ## with A and N sized for DC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [9, 10, 12, 10, 11, 13] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 14)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [12, 13])), (2, 14)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 1 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) ## with A and N sized for AC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [18, 19, 24, 19, 20, 25] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 26)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [24, 25])), (2, 26)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 2 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) t = ''.join([t0, 'infeasible : ']) ## with A and N sized for DC opf ppc = loadcase(casefile) ppc['A'] = sparse(([1, 1], ([0, 0], [9, 10])), (1, 14)) ## Pg1 + Pg2 ppc['u'] = array([Inf]) ppc['l'] = array([600]) r = rundcopf(ppc, ppopt) t_ok(not r['success'], [t, 'no success']) else: t_skip(num_tests, 'Gurobi not available') t_end()
def runpf(casedata=None, ppopt=None, fname='', solvedcase=''): """Runs a power flow. Runs a power flow [full AC Newton's method by default] and optionally returns the solved values in the data matrices, a flag which is C{True} if the algorithm was successful in finding a solution, and the elapsed time in seconds. All input arguments are optional. If C{casename} is provided it specifies the name of the input data file or dict containing the power flow data. The default value is 'case9'. If the ppopt is provided it overrides the default PYPOWER options vector and can be used to specify the solution algorithm and output options among other things. If the 3rd argument is given the pretty printed output will be appended to the file whose name is given in C{fname}. If C{solvedcase} is specified the solved case will be written to a case file in PYPOWER format with the specified name. If C{solvedcase} ends with '.mat' it saves the case as a MAT-file otherwise it saves it as a Python-file. If the C{ENFORCE_Q_LIMS} options is set to C{True} [default is false] then if any generator reactive power limit is violated after running the AC power flow, the corresponding bus is converted to a PQ bus, with Qg at the limit, and the case is re-run. The voltage magnitude at the bus will deviate from the specified value in order to satisfy the reactive power limit. If the reference bus is converted to PQ, the first remaining PV bus will be used as the slack bus for the next iteration. This may result in the real power output at this generator being slightly off from the specified values. Enforcing of generator Q limits inspired by contributions from Mu Lin, Lincoln University, New Zealand (1/14/05). @author: Ray Zimmerman (PSERC Cornell) """ ## default arguments if casedata is None: casedata = join(dirname(__file__), 'case9') ppopt = ppoption(ppopt) ## options verbose = ppopt["VERBOSE"] qlim = ppopt["ENFORCE_Q_LIMS"] ## enforce Q limits on gens? dc = ppopt["PF_DC"] ## use DC formulation? ## read data ppc = loadcase(casedata) ## add zero columns to branch for flows if needed if ppc["branch"].shape[1] < QT: ppc["branch"] = c_[ppc["branch"], zeros((ppc["branch"].shape[0], QT - ppc["branch"].shape[1] + 1))] ## convert to internal indexing ppc = ext2int(ppc) baseMVA, bus, gen, branch = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] ## get bus index lists of each type of bus ref, pv, pq = bustypes(bus, gen) ## generator info on = find(gen[:, GEN_STATUS] > 0) ## which generators are on? gbus = gen[on, GEN_BUS].astype(int) ## what buses are they at? ##----- run the power flow ----- t0 = time() if verbose > 0: v = ppver('all') stdout.write('PYPOWER Version %s, %s' % (v["Version"], v["Date"])) if dc: # DC formulation if verbose: stdout.write(' -- DC Power Flow\n') ## initial state Va0 = bus[:, VA] * (pi / 180) ## build B matrices and phase shift injections B, Bf, Pbusinj, Pfinj = makeBdc(baseMVA, bus, branch) ## compute complex bus power injections [generation - load] ## adjusted for phase shifters and real shunts Pbus = makeSbus(baseMVA, bus, gen).real - Pbusinj - bus[:, GS] / baseMVA ## "run" the power flow Va = dcpf(B, Pbus, Va0, ref, pv, pq) ## update data matrices with solution branch[:, [QF, QT]] = zeros((branch.shape[0], 2)) branch[:, PF] = (Bf * Va + Pfinj) * baseMVA branch[:, PT] = -branch[:, PF] bus[:, VM] = ones(bus.shape[0]) bus[:, VA] = Va * (180 / pi) ## update Pg for slack generator (1st gen at ref bus) ## (note: other gens at ref bus are accounted for in Pbus) ## Pg = Pinj + Pload + Gs ## newPg = oldPg + newPinj - oldPinj refgen = zeros(len(ref), dtype=int) for k in range(len(ref)): temp = find(gbus == ref[k]) refgen[k] = on[temp[0]] gen[refgen, PG] = gen[refgen, PG] + (B[ref, :] * Va - Pbus[ref]) * baseMVA success = 1 else: ## AC formulation alg = ppopt['PF_ALG'] if verbose > 0: if alg == 1: solver = 'Newton' elif alg == 2: solver = 'fast-decoupled, XB' elif alg == 3: solver = 'fast-decoupled, BX' elif alg == 4: solver = 'Gauss-Seidel' else: solver = 'unknown' print(' -- AC Power Flow (%s)\n' % solver) ## initial state # V0 = ones(bus.shape[0]) ## flat start V0 = bus[:, VM] * exp(1j * pi/180 * bus[:, VA]) V0[gbus] = gen[on, VG] / abs(V0[gbus]) * V0[gbus] if qlim: ref0 = ref ## save index and angle of Varef0 = bus[ref0, VA] ## original reference bus(es) limited = [] ## list of indices of gens @ Q lims fixedQg = zeros(gen.shape[0]) ## Qg of gens at Q limits repeat = True while repeat: ## build admittance matrices Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch) ## compute complex bus power injections [generation - load] Sbus = makeSbus(baseMVA, bus, gen) ## run the power flow alg = ppopt["PF_ALG"] if alg == 1: V, success, _ = newtonpf(Ybus, Sbus, V0, ref, pv, pq, ppopt) elif alg == 2 or alg == 3: Bp, Bpp = makeB(baseMVA, bus, branch, alg) V, success, _ = fdpf(Ybus, Sbus, V0, Bp, Bpp, ref, pv, pq, ppopt) elif alg == 4: V, success, _ = gausspf(Ybus, Sbus, V0, ref, pv, pq, ppopt) else: stderr.write('Only Newton''s method, fast-decoupled, and ' 'Gauss-Seidel power flow algorithms currently ' 'implemented.\n') ## update data matrices with solution bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref, pv, pq) if qlim: ## enforce generator Q limits ## find gens with violated Q constraints gen_status = gen[:, GEN_STATUS] > 0 qg_max_lim = gen[:, QG] > gen[:, QMAX] qg_min_lim = gen[:, QG] < gen[:, QMIN] mx = find( gen_status & qg_max_lim ) mn = find( gen_status & qg_min_lim ) if len(mx) > 0 or len(mn) > 0: ## we have some Q limit violations # No PV generators if len(pv) == 0: if verbose: if len(mx) > 0: print('Gen %d [only one left] exceeds upper Q limit : INFEASIBLE PROBLEM\n' % mx + 1) else: print('Gen %d [only one left] exceeds lower Q limit : INFEASIBLE PROBLEM\n' % mn + 1) success = 0 break ## one at a time? if qlim == 2: ## fix largest violation, ignore the rest k = argmax(r_[gen[mx, QG] - gen[mx, QMAX], gen[mn, QMIN] - gen[mn, QG]]) if k > len(mx): mn = mn[k - len(mx)] mx = [] else: mx = mx[k] mn = [] if verbose and len(mx) > 0: for i in range(len(mx)): print('Gen ' + str(mx[i] + 1) + ' at upper Q limit, converting to PQ bus\n') if verbose and len(mn) > 0: for i in range(len(mn)): print('Gen ' + str(mn[i] + 1) + ' at lower Q limit, converting to PQ bus\n') ## save corresponding limit values fixedQg[mx] = gen[mx, QMAX] fixedQg[mn] = gen[mn, QMIN] mx = r_[mx, mn].astype(int) ## convert to PQ bus gen[mx, QG] = fixedQg[mx] ## set Qg to binding for i in range(len(mx)): ## [one at a time, since they may be at same bus] gen[mx[i], GEN_STATUS] = 0 ## temporarily turn off gen, bi = gen[mx[i], GEN_BUS] ## adjust load accordingly, bus[bi, [PD, QD]] = (bus[bi, [PD, QD]] - gen[mx[i], [PG, QG]]) if len(ref) > 1 and any(bus[gen[mx, GEN_BUS], BUS_TYPE] == REF): raise ValueError('Sorry, PYPOWER cannot enforce Q ' 'limits for slack buses in systems ' 'with multiple slacks.') bus[gen[mx, GEN_BUS].astype(int), BUS_TYPE] = PQ ## & set bus type to PQ ## update bus index lists of each type of bus ref_temp = ref ref, pv, pq = bustypes(bus, gen) if verbose and ref != ref_temp: print('Bus %d is new slack bus\n' % ref) limited = r_[limited, mx].astype(int) else: repeat = 0 ## no more generator Q limits violated else: repeat = 0 ## don't enforce generator Q limits, once is enough if qlim and len(limited) > 0: ## restore injections from limited gens [those at Q limits] gen[limited, QG] = fixedQg[limited] ## restore Qg value, for i in range(len(limited)): ## [one at a time, since they may be at same bus] bi = gen[limited[i], GEN_BUS] ## re-adjust load, bus[bi, [PD, QD]] = bus[bi, [PD, QD]] + gen[limited[i], [PG, QG]] gen[limited[i], GEN_STATUS] = 1 ## and turn gen back on if ref != ref0: ## adjust voltage angles to make original ref bus correct bus[:, VA] = bus[:, VA] - bus[ref0, VA] + Varef0 ppc["et"] = time() - t0 ppc["success"] = success ##----- output results ----- ## convert back to original bus numbering & print results ppc["bus"], ppc["gen"], ppc["branch"] = bus, gen, branch results = int2ext(ppc) ## zero out result fields of out-of-service gens & branches if len(results["order"]["gen"]["status"]["off"]) > 0: results["gen"][ix_(results["order"]["gen"]["status"]["off"], [PG, QG])] = 0 if len(results["order"]["branch"]["status"]["off"]) > 0: results["branch"][ix_(results["order"]["branch"]["status"]["off"], [PF, QF, PT, QT])] = 0 if fname: fd = None try: fd = open(fname, "a") except Exception as detail: stderr.write("Error opening %s: %s.\n" % (fname, detail)) finally: if fd is not None: printpf(results, fd, ppopt) fd.close() else: printpf(results, stdout, ppopt) ## save solved case if solvedcase: savecase(solvedcase, results) return results, success
def t_opf_userfcns(quiet=False): """Tests for userfcn callbacks (reserves/iflims) w/OPF. Includes high-level tests of reserves and iflims implementations. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ t_begin(38, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case30_userfcns') verbose = 0 #not quiet ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=560, OPF_ALG_DC=200) #ppopt = ppoption(ppopt, OUT_ALL=-1, VERBOSE=2, OUT_GEN=1) ## run the OPF with fixed reserves t = 'fixed reserves : ' ppc = loadcase(casefile) ppc = toggle_reserves(ppc, 'on') r = runopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'reserves.R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4, [t, 'reserves.mu.Pmax']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4, [t, 'reserves.mu.u']) t_ok('P' not in r['if'], [t, 'no iflims']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t = 'toggle_reserves(ppc, \'off\') : ' ppc = toggle_reserves(ppc, 'off') r = runopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_ok('R' not in r['reserves'], [t, 'no reserves']) t_ok('P' not in r['if'], [t, 'no iflims']) t = 'interface flow lims (DC) : ' ppc = loadcase(casefile) ppc = toggle_iflims(ppc, 'on') r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P']) t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u']) t_is(r['branch'][13, PF], 8.244, 3, [t, 'flow in branch 14']) t_ok('R' not in r['reserves'], [t, 'no reserves']) t = 'reserves + interface flow lims (DC) : ' ppc = loadcase(casefile) ppc = toggle_reserves(ppc, 'on') ppc = toggle_iflims(ppc, 'on') r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P']) t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 38.2573], 4, [t, 'if.mu.u']) t_is(r['reserves']['R'], [25, 15, 0, 0, 16.9, 3.1], 4, [t, 'reserves.R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4, [t, 'reserves.mu.Pmax']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4, [t, 'reserves.mu.u']) t_is(r['reserves']['totalcost'], 179.05, 4, [t, 'totalcost']) t = 'interface flow lims (AC) : ' ppc = toggle_reserves(ppc, 'off') r = runopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-9.101, 21.432], 3, [t, 'if.P']) t_is(r['if']['mu']['l'], [0, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 10.198], 3, [t, 'if.mu.u']) t_ok('R' not in r['reserves'], [t, 'no reserves']) t = 'interface flow lims (line out) : ' ppc = loadcase(casefile) ppc = toggle_iflims(ppc, 'on') ppc['branch'][11, BR_STATUS] = 0 ## take out line 6-10 r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P']) t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u']) t_is(r['branch'][13, PF], 10.814, 3, [t, 'flow in branch 14']) t_ok('R' not in r['reserves'], [t, 'no reserves']) # r['reserves']['R'] # r['reserves']['prc'] # r['reserves']['mu.Pmax'] # r['reserves']['mu']['l'] # r['reserves']['mu']['u'] # r['reserves']['totalcost'] # # r['if']['P'] # r['if']['mu']['l'] # r['if']['mu']['u'] t_end()
def t_opf_dc_pips(quiet=False): """Tests for DC optimal power flow using PIPS solver. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ num_tests = 23 t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_opf') verbose = 0#not quiet t0 = 'DC OPF (PIPS): ' ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0, OPF_ALG_DC=200) ## run DC OPF ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) #ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## get solved DC power flow case from MAT-file soln9_dcopf = loadmat(join(tdir, 'soln9_dcopf.mat'), struct_as_record=True) ## defines bus_soln, gen_soln, branch_soln, f_soln bus_soln = soln9_dcopf['bus_soln'] gen_soln = soln9_dcopf['gen_soln'] branch_soln = soln9_dcopf['branch_soln'] f_soln = soln9_dcopf['f_soln'][0] ## run OPF t = t0 r = rundcopf(casefile, ppopt) bus, gen, branch, f, success = \ r['bus'], r['gen'], r['branch'], r['f'], r['success'] t_ok(success, [t, 'success']) t_is(f, f_soln, 3, [t, 'f']) t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data']) t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage']) t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda']) t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu']) t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data']) t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch']) t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu']) t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data']) t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow']) t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu']) ##----- run OPF with extra linear user constraints & costs ----- ## two new z variables ## 0 <= z1, P2 - P1 <= z1 ## 0 <= z2, P2 - P3 <= z2 ## with A and N sized for DC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [9, 10, 12, 10, 11, 13] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 14)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [12, 13])), (2, 14)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 1 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) ## with A and N sized for AC opf ppc = loadcase(casefile) row = [0, 0, 0, 1, 1, 1] col = [18, 19, 24, 19, 20, 25] ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 26)) ppc['u'] = array([0, 0]) ppc['l'] = array([-Inf, -Inf]) ppc['zl'] = array([0, 0]) ppc['N'] = sparse(([1, 1], ([0, 1], [24, 25])), (2, 26)) ## new z variables only ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]]) ## w = r = z ppc['H'] = sparse((2, 2)) ## no quadratic term ppc['Cw'] = array([1000, 1]) t = ''.join([t0, 'w/extra constraints & costs 2 : ']) r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974']) t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974']) t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars']) t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs']) t = ''.join([t0, 'infeasible : ']) ## with A and N sized for DC opf ppc = loadcase(casefile) ppc['A'] = sparse(([1, 1], ([0, 0], [9, 10])), (1, 14)) ## Pg1 + Pg2 ppc['u'] = array([Inf]) ppc['l'] = array([600]) r = rundcopf(ppc, ppopt) t_ok(not r['success'], [t, 'no success']) t_end()
def t_runmarket(quiet=False): """Tests for code in C{runmkt}, C{smartmkt} and C{auction}. @author: Ray Zimmerman (PSERC Cornell) """ n_tests = 20 t_begin(n_tests, quiet) try: from pypower.extras.smartmarket import runmarket except ImportError: t_skip(n_tests, 'smartmarket code not available') t_end return ppc = loadcase('t_auction_case') ppopt = ppoption(OPF_ALG=560, OUT_ALL_LIM=1, OUT_BRANCH=0, OUT_SYS_SUM=0) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=1) #ppopt = ppoption(ppopt, OUT_GEN=1, OUT_BRANCH=0, OUT_SYS_SUM=0) offers = {'P': {}, 'Q': {}} bids = {'P': {}, 'Q': {}} offers['P']['qty'] = array([[12, 24, 24], [12, 24, 24], [12, 24, 24], [12, 24, 24], [12, 24, 24], [12, 24, 24]]) offers['P']['prc'] = array([[20, 50, 60], [20, 40, 70], [20, 42, 80], [20, 44, 90], [20, 46, 75], [20, 48, 60]]) bids['P']['qty'] = array([[10, 10, 10], [10, 10, 10], [10, 10, 10]]) bids['P']['prc'] = array([ [100, 70, 60], # [100, 64.3, 20], # [100, 30.64545, 0], [100, 50, 20], [100, 60, 50] ]) offers['Q']['qty'] = [60, 60, 60, 60, 60, 60, 0, 0, 0] offers['Q']['prc'] = [0, 0, 0, 0, 0, 3, 0, 0, 0] bids.Q['qty'] = [15, 15, 15, 15, 15, 15, 15, 12, 7.5] # bids.Q['prc'] = [ 0, 0, 0, 0, 0, 0, 0, 83.9056, 0 ] bids.Q['prc'] = [0, 0, 0, 0, 0, 0, 0, 20, 0] t = 'marginal Q offer, marginal PQ bid, auction_type = 5' mkt = {'auction_type': 5, 't': [], 'u0': [], 'lim': []} r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt) co5 = co.copy() cb5 = cb.copy() # [ co['P']['qty'] co['P']['prc'] ] # [ cb['P']['qty'] cb['P']['prc'] ] # [ co['Q']['qty'] co['Q']['prc'] ] # [ cb['Q']['qty'] cb['Q']['prc'] ] i2e = r['bus'][:, BUS_I] e2i = sparse((max(i2e), 1)) e2i[i2e] = list(range(r['bus'].size)) G = find(isload(r['gen']) == 0) ## real generators L = find(isload(r['gen'])) ## dispatchable loads Gbus = e2i[r['gen'][G, GEN_BUS]] Lbus = e2i[r['gen'][L, GEN_BUS]] t_is(co['P']['qty'], ones((6, 1)) * [12, 24, 0], 2, [t, ' : gen P quantities']) t_is(co['P']['prc'][0, :], 50.1578, 3, [t, ' : gen 1 P prices']) t_is(cb['P']['qty'], [[10, 10, 10], [10, 0.196, 0], [10, 10, 0]], 2, [t, ' : load P quantities']) t_is(cb['P']['prc'][1, :], 56.9853, 4, [t, ' : load 2 P price']) t_is(co['P']['prc'][:, 0], r['bus'][Gbus, LAM_P], 8, [t, ' : gen P prices']) t_is(cb['P']['prc'][:, 0], r['bus'][Lbus, LAM_P], 8, [t, ' : load P prices']) t_is(co['Q']['qty'], [4.2722, 11.3723, 14.1472, 22.8939, 36.7886, 12.3375, 0, 0, 0], 2, [t, ' : Q offer quantities']) t_is(co['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4, [t, ' : Q offer prices']) t_is(cb['Q']['qty'], [0, 0, 0, 0, 0, 0, 15, 4.0785, 5], 2, [t, ' : Q bid quantities']) t_is(cb['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4, [t, ' : Q bid prices']) t_is(co['Q']['prc'], r['bus'][[Gbus, Lbus], LAM_Q], 8, [t, ' : Q offer prices']) t_is(cb['Q']['prc'], co['Q']['prc'], 8, [t, ' : Q bid prices']) t = 'marginal Q offer, marginal PQ bid, auction_type = 0' mkt['auction_type'] = 0 r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt) t_is(co['P']['qty'], co5['P']['qty'], 8, [t, ' : gen P quantities']) t_is(cb['P']['qty'], cb5['P']['qty'], 8, [t, ' : load P quantities']) t_is(co['P']['prc'], offers['P']['prc'], 8, [t, ' : gen P prices']) t_is(cb['P']['prc'], bids['P']['prc'], 8, [t, ' : load P prices']) t_is(co['Q']['qty'], co5['Q']['qty'], 8, [t, ' : gen Q quantities']) t_is(cb['Q']['qty'], cb5['Q']['qty'], 8, [t, ' : load Q quantities']) t_is(co['Q']['prc'], offers['Q']['prc'], 8, [t, ' : gen Q prices']) t_is(cb['Q']['prc'], bids['Q']['prc'], 8, [t, ' : load Q prices']) t_end
import matplotlib.pyplot as plt import numpy as np from omf.scratch.transients import montefaults as mf if __name__ == '__main__': ######### # SETUP # ######### print('----------------------------------------') print('PYPOWER-Dynamics - Classical 9 Bus Test') print('----------------------------------------') # Load PYPOWER case ppc = loadcase('ocrakoke.py') # Program options dynopt = {} dynopt['h'] = 0.001 # step length (s) dynopt['t_sim'] = 200.0 # simulation time (s) dynopt[ 'max_err'] = 1e-6 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 60 # Nominal system frequency (Hz) # Integrator option dynopt['iopt'] = 'mod_euler' #dynopt['iopt'] = 'runge_kutta'
def t_pf(quiet=False): """Tests for power flow solvers. @author: Ray Zimmerman (PSERC Cornell) """ t_begin(33, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_pf') verbose = not quiet ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] ## run Newton PF t = 'Newton PF : '; ppopt = ppoption(ppopt, PF_ALG=1) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (XB version) t = 'Fast Decoupled (XB) PF : '; ppopt = ppoption(ppopt, PF_ALG=2) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (BX version) t = 'Fast Decoupled (BX) PF : '; ppopt = ppoption(ppopt, PF_ALG=3) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run Gauss-Seidel PF t = 'Gauss-Seidel PF : '; ppopt = ppoption(ppopt, PF_ALG=4) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 5, [t, 'bus']) t_is(gen, gen_soln, 5, [t, 'gen']) t_is(branch, branch_soln, 5, [t, 'branch']) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_dcpf = loadmat(join(tdir, 'soln9_dcpf.mat'), struct_as_record=False) bus_soln = soln9_dcpf['bus_soln'] gen_soln = soln9_dcpf['gen_soln'] branch_soln = soln9_dcpf['branch_soln'] ## run DC PF t = 'DC PF : ' results, success = rundcpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## check Qg distribution, when Qmin = Qmax t = 'check Qg : ' ppopt = ppoption(ppopt, PF_ALG=1, VERBOSE=0) ppc = loadcase(casefile) ppc['gen'][0, [QMIN, QMAX]] = [20, 20] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0, QG], 24.07, 2, [t, 'single gen, Qmin = Qmax']) ppc['gen'] = r_[array([ ppc['gen'][0, :] ]), ppc['gen']] ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [ 0, 50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [10, 14.07], 2, [t, '2 gens, Qmin = Qmax for one']) ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [-50, -50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [12.03, 12.03], 2, [t, '2 gens, Qmin = Qmax for both']) ppc['gen'][0, [QMIN, QMAX]] = [0, 50] ppc['gen'][1, [QMIN, QMAX]] = [0, 100] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [8.02, 16.05], 2, [t, '2 gens, proportional']) ppc['gen'][0, [QMIN, QMAX]] = [-50, 0] ppc['gen'][1, [QMIN, QMAX]] = [50, 150] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [-50 + 8.02, 50 + 16.05], 2, [t, '2 gens, proportional']) ## network with islands t = 'network w/islands : DC PF : ' ppc0 = loadcase(casefile) ppc0['gen'][0, PG] = 60 ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] = \ ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] / 2 ppc0['gen'] = r_[array([ ppc0['gen'][0, :] ]), ppc0['gen']] ppc1 = ppc0.copy() ppc = ppc0.copy() nb = ppc['bus'].shape[0] ppc1['bus'][:, BUS_I] = ppc1['bus'][:, BUS_I] + nb ppc1['branch'][:, F_BUS] = ppc1['branch'][:, F_BUS] + nb ppc1['branch'][:, T_BUS] = ppc1['branch'][:, T_BUS] + nb ppc1['gen'][:, GEN_BUS] = ppc1['gen'][:, GEN_BUS] + nb ppc['bus'] = r_[ppc['bus'], ppc1['bus']] ppc['branch'] = r_[ppc['branch'], ppc1['branch']] ppc['gen'] = r_[ppc['gen'], ppc1['gen']] #ppopt = ppoption(ppopt, OUT_BUS=1, OUT_GEN=1, OUT_ALL=-1, VERBOSE=2) ppopt = ppoption(ppopt, VERBOSE=verbose) r = rundcpf(ppc, ppopt) t_is(r['bus'][ :9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][10:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][ :4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t = 'network w/islands : AC PF : ' ## get solved AC power flow case from MAT-file soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] r = runpf(ppc, ppopt) t_is(r['bus'][ :9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][9:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][ :4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t_end()
from freadexcel import freadexcel from fstoreresult import fstoreresult from fwriteinexcel import fwriteinexcel import os import numpy as np # Names of the data folder and output files foldername = 'Data_été' filename = 'results_name.txt' xlsname = 'results_name.xls' mapname = 'map_name.png' # Extracting data from xls files and creating 4 ppc matrices os.chdir(foldername) ppc = loadcase(caseproject()) bus, gen, branch, gencost = freadexcel() ppc["bus"] = bus ppc["branch"] = branch ppc["gen"] = gen ppc["gencost"] = gencost # Running the simulation r = rundcopf(ppc, fname=filename) # Storing results results_gen, results_load_lambda, results_branch = fstoreresult(r) # Writing results in xls file # fwriteinexcel(xlsname, results_gen, results_load_lambda, results_branch)
from pypower.idx_bus import BUS_TYPE, BUS_AREA, PD, QD from pypower.idx_gen import GEN_STATUS, GEN_BUS, PMAX, PMIN, QMAX, QMIN from pypower.idx_cost import COST from findTieline import findTieline from runWorker import runWorker from opf_admm_model import opf_admm_model os.system("taskset -p 0xff %d" % os.getpid()) #---------------- basic system configuration --------------------------------- caseFile = join( '/Users/junyaoguo/anaconda/lib/python3.5/site-packages/pypower', 'case14') # load a test power system ppc = loadcase(caseFile) # convert to internal numbering, remove out-of-service stuff ppc = ext2int(ppc) baseMVA, bus, gen, branch, gencost = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"] slack = find(bus[:, BUS_TYPE] == 3) # an array of indices gen_active = find(gen[:, GEN_STATUS] == 1) genBus = gen[gen_active, GEN_BUS] ## convert to p.u. bus[:, [PD, QD]] /= baseMVA gen[:, [PMAX, PMIN, QMAX, QMIN]] /= baseMVA gencost[:, COST] *= baseMVA**2 gencost[:, COST + 1] *= baseMVA ## problem dimensions
def t_dcline(quiet=False): """Tests for DC line extension in L{{toggle_dcline}. @author: Ray Zimmerman (PSERC Cornell) """ num_tests = 50 t_begin(num_tests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_dcline') if quiet: verbose = False else: verbose = False t0 = '' ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OPF_ALG=560, OPF_ALG_DC=200) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose) ## set up indices ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)] ib_voltage = arange(VM, VA + 1) ib_lam = arange(LAM_P, LAM_Q + 1) ib_mu = arange(MU_VMAX, MU_VMIN + 1) ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)] ig_disp = array([PG, QG, VG]) ig_mu = arange(MU_PMAX, MU_QMIN + 1) ibr_data = arange(ANGMAX + 1) ibr_flow = arange(PF, QT + 1) ibr_mu = array([MU_SF, MU_ST]) ibr_angmu = array([MU_ANGMIN, MU_ANGMAX]) ## load case ppc0 = loadcase(casefile) del ppc0['dclinecost'] ppc = ppc0 ppc = toggle_dcline(ppc, 'on') ppc = toggle_dcline(ppc, 'off') ndc = ppc['dcline'].shape[0] ## run AC OPF w/o DC lines t = ''.join([t0, 'AC OPF (no DC lines) : ']) r0 = runopf(ppc0, ppopt) success = r0['success'] t_ok(success, [t, 'success']) r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) t_is(r['f'], r0['f'], 8, [t, 'f']) t_is(r['bus'][:, ib_data], r0['bus'][:, ib_data], 10, [t, 'bus data']) t_is(r['bus'][:, ib_voltage], r0['bus'][:, ib_voltage], 3, [t, 'bus voltage']) t_is(r['bus'][:, ib_lam], r0['bus'][:, ib_lam], 3, [t, 'bus lambda']) t_is(r['bus'][:, ib_mu], r0['bus'][:, ib_mu], 2, [t, 'bus mu']) t_is(r['gen'][:, ig_data], r0['gen'][:, ig_data], 10, [t, 'gen data']) t_is(r['gen'][:, ig_disp], r0['gen'][:, ig_disp], 3, [t, 'gen dispatch']) t_is(r['gen'][:, ig_mu], r0['gen'][:, ig_mu], 3, [t, 'gen mu']) t_is(r['branch'][:, ibr_data], r0['branch'][:, ibr_data], 10, [t, 'branch data']) t_is(r['branch'][:, ibr_flow], r0['branch'][:, ibr_flow], 3, [t, 'branch flow']) t_is(r['branch'][:, ibr_mu], r0['branch'][:, ibr_mu], 2, [t, 'branch mu']) t = ''.join([t0, 'AC PF (no DC lines) : ']) ppc1 = { 'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy() } ppc1['bus'][:, VM] = 1 ppc1['bus'][:, VA] = 0 rp = runpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is(rp['bus'][:, ib_voltage], r['bus'][:, ib_voltage], 3, [t, 'bus voltage']) t_is(rp['gen'][:, ig_disp], r['gen'][:, ig_disp], 3, [t, 'gen dispatch']) t_is(rp['branch'][:, ibr_flow], r['branch'][:, ibr_flow], 3, [t, 'branch flow']) ## run with DC lines t = ''.join([t0, 'AC OPF (with DC lines) : ']) ppc = toggle_dcline(ppc, 'on') r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) expected = array([[10, 8.9, -10, 10, 1.0674, 1.0935], [2.2776, 2.2776, 0, 0, 1.0818, 1.0665], [0, 0, 0, 0, 1.0000, 1.0000], [10, 9.5, 0.0563, -10, 1.0778, 1.0665]]) t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V']) expected = array([[0, 0.8490, 0.6165, 0, 0, 0.2938], [0, 0, 0, 0.4290, 0.0739, 0], [0, 0, 0, 0, 0, 0], [0, 7.2209, 0, 0, 0.0739, 0]]) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu']) t = ''.join([t0, 'AC PF (with DC lines) : ']) ppc1 = { 'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy() } ppc1 = toggle_dcline(ppc1, 'on') ppc1['bus'][:, VM] = 1 ppc1['bus'][:, VA] = 0 rp = runpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is(rp['bus'][:, ib_voltage], r['bus'][:, ib_voltage], 3, [t, 'bus voltage']) #t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch']) t_is(rp['gen'][:2, ig_disp], r['gen'][:2, ig_disp], 3, [t, 'gen dispatch']) t_is(rp['gen'][2, PG], r['gen'][2, PG], 3, [t, 'gen dispatch']) t_is(rp['gen'][2, QG] + rp['dcline'][0, c.QF], r['gen'][2, QG] + r['dcline'][0, c.QF], 3, [t, 'gen dispatch']) t_is(rp['branch'][:, ibr_flow], r['branch'][:, ibr_flow], 3, [t, 'branch flow']) ## add appropriate P and Q injections and check angles and generation when running PF t = ''.join([t0, 'AC PF (with equivalent injections) : ']) ppc1 = { 'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy() } ppc1['bus'][:, VM] = 1 ppc1['bus'][:, VA] = 0 for k in range(ndc): if ppc1['dcline'][k, c.BR_STATUS]: ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS]) tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS]) ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF] ppc1['bus'][ff, QD] = ppc1['bus'][ff, QD] - r['dcline'][k, c.QF] ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT] ppc1['bus'][tt, QD] = ppc1['bus'][tt, QD] - r['dcline'][k, c.QT] ppc1['bus'][ff, VM] = r['dcline'][k, c.VF] ppc1['bus'][tt, VM] = r['dcline'][k, c.VT] ppc1['bus'][ff, BUS_TYPE] = PV ppc1['bus'][tt, BUS_TYPE] = PV rp = runpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is(rp['bus'][:, ib_voltage], r['bus'][:, ib_voltage], 3, [t, 'bus voltage']) t_is(rp['gen'][:, ig_disp], r['gen'][:, ig_disp], 3, [t, 'gen dispatch']) t_is(rp['branch'][:, ibr_flow], r['branch'][:, ibr_flow], 3, [t, 'branch flow']) ## test DC OPF t = ''.join([t0, 'DC OPF (with DC lines) : ']) ppc = ppc0.copy() ppc['gen'][0, PMIN] = 10 ppc['branch'][4, RATE_A] = 100 ppc = toggle_dcline(ppc, 'on') r = rundcopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) expected = array([[10, 8.9, 0, 0, 1.01, 1], [2, 2, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1], [10, 9.5, 0, 0, 1, 0.98]]) t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V']) expected = array([[0, 1.8602, 0, 0, 0, 0], [1.8507, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0.2681, 0, 0, 0, 0]]) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu']) t = ''.join([t0, 'DC PF (with DC lines) : ']) ppc1 = { 'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy() } ppc1 = toggle_dcline(ppc1, 'on') ppc1['bus'][:, VA] = 0 rp = rundcpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is(rp['bus'][:, ib_voltage], r['bus'][:, ib_voltage], 3, [t, 'bus voltage']) t_is(rp['gen'][:, ig_disp], r['gen'][:, ig_disp], 3, [t, 'gen dispatch']) t_is(rp['branch'][:, ibr_flow], r['branch'][:, ibr_flow], 3, [t, 'branch flow']) ## add appropriate P injections and check angles and generation when running PF t = ''.join([t0, 'DC PF (with equivalent injections) : ']) ppc1 = { 'baseMVA': r['baseMVA'], 'bus': r['bus'][:, :VMIN + 1].copy(), 'gen': r['gen'][:, :APF + 1].copy(), 'branch': r['branch'][:, :ANGMAX + 1].copy(), 'gencost': r['gencost'].copy(), 'dcline': r['dcline'][:, :c.LOSS1 + 1].copy() } ppc1['bus'][:, VA] = 0 for k in range(ndc): if ppc1['dcline'][k, c.BR_STATUS]: ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS]) tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS]) ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF] ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT] ppc1['bus'][ff, BUS_TYPE] = PV ppc1['bus'][tt, BUS_TYPE] = PV rp = rundcpf(ppc1, ppopt) success = rp['success'] t_ok(success, [t, 'success']) t_is(rp['bus'][:, ib_voltage], r['bus'][:, ib_voltage], 3, [t, 'bus voltage']) t_is(rp['gen'][:, ig_disp], r['gen'][:, ig_disp], 3, [t, 'gen dispatch']) t_is(rp['branch'][:, ibr_flow], r['branch'][:, ibr_flow], 3, [t, 'branch flow']) ## run with DC lines t = ''.join([t0, 'AC OPF (with DC lines + poly cost) : ']) ppc = loadcase(casefile) ppc = toggle_dcline(ppc, 'on') r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) expected1 = array([[10, 8.9, -10, 10, 1.0663, 1.0936], [7.8429, 7.8429, 0, 0, 1.0809, 1.0667], [0, 0, 0, 0, 1.0000, 1.0000], [6.0549, 5.7522, -0.5897, -10, 1.0778, 1.0667]]) t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V']) expected2 = array([[0, 0.7605, 0.6226, 0, 0, 0.2980], [0, 0, 0, 0.4275, 0.0792, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0.0792, 0]]) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu']) ppc['dclinecost'][3, :8] = array([2, 0, 0, 4, 0, 0, 7.3, 0]) r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V']) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu']) t = ''.join([t0, 'AC OPF (with DC lines + pwl cost) : ']) ppc['dclinecost'][3, :8] = array([1, 0, 0, 2, 0, 0, 10, 73]) r = runopf(ppc, ppopt) success = r['success'] t_ok(success, [t, 'success']) t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V']) t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu']) t_end()
def t_runmarket(quiet=False): """Tests for code in C{runmkt}, C{smartmkt} and C{auction}. @author: Ray Zimmerman (PSERC Cornell) """ n_tests = 20 t_begin(n_tests, quiet) try: from pypower.extras.smartmarket import runmarket except ImportError: t_skip(n_tests, 'smartmarket code not available') t_end; return ppc = loadcase('t_auction_case') ppopt = ppoption(OPF_ALG=560, OUT_ALL_LIM=1, OUT_BRANCH=0, OUT_SYS_SUM=0) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=1) #ppopt = ppoption(ppopt, OUT_GEN=1, OUT_BRANCH=0, OUT_SYS_SUM=0) offers = {'P': {}, 'Q': {}} bids = {'P': {}, 'Q': {}} offers['P']['qty'] = array([ [12, 24, 24], [12, 24, 24], [12, 24, 24], [12, 24, 24], [12, 24, 24], [12, 24, 24] ]) offers['P']['prc'] = array([ [20, 50, 60], [20, 40, 70], [20, 42, 80], [20, 44, 90], [20, 46, 75], [20, 48, 60] ]) bids['P']['qty'] = array([ [10, 10, 10], [10, 10, 10], [10, 10, 10] ]) bids['P']['prc'] = array([ [100, 70, 60], # [100, 64.3, 20], # [100, 30.64545, 0], [100, 50, 20], [100, 60, 50] ]) offers['Q']['qty'] = [ 60, 60, 60, 60, 60, 60, 0, 0, 0 ] offers['Q']['prc'] = [ 0, 0, 0, 0, 0, 3, 0, 0, 0 ] bids.Q['qty'] = [ 15, 15, 15, 15, 15, 15, 15, 12, 7.5 ] # bids.Q['prc'] = [ 0, 0, 0, 0, 0, 0, 0, 83.9056, 0 ] bids.Q['prc'] = [ 0, 0, 0, 0, 0, 0, 0, 20, 0 ] t = 'marginal Q offer, marginal PQ bid, auction_type = 5' mkt = {'auction_type': 5, 't': [], 'u0': [], 'lim': []} r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt) co5 = co.copy() cb5 = cb.copy() # [ co['P']['qty'] co['P']['prc'] ] # [ cb['P']['qty'] cb['P']['prc'] ] # [ co['Q']['qty'] co['Q']['prc'] ] # [ cb['Q']['qty'] cb['Q']['prc'] ] i2e = r['bus'][:, BUS_I] e2i = sparse((max(i2e), 1)) e2i[i2e] = range(r['bus'].size) G = find( isload(r['gen']) == 0 ) ## real generators L = find( isload(r['gen']) ) ## dispatchable loads Gbus = e2i[r['gen'][G, GEN_BUS]] Lbus = e2i[r['gen'][L, GEN_BUS]] t_is( co['P']['qty'], ones((6, 1)) * [12, 24, 0], 2, [t, ' : gen P quantities'] ) t_is( co['P']['prc'][0, :], 50.1578, 3, [t, ' : gen 1 P prices'] ) t_is( cb['P']['qty'], [[10, 10, 10], [10, 0.196, 0], [10, 10, 0]], 2, [t, ' : load P quantities'] ) t_is( cb['P']['prc'][1, :], 56.9853, 4, [t, ' : load 2 P price'] ) t_is( co['P']['prc'][:, 0], r['bus'][Gbus, LAM_P], 8, [t, ' : gen P prices'] ) t_is( cb['P']['prc'][:, 0], r['bus'][Lbus, LAM_P], 8, [t, ' : load P prices'] ) t_is( co['Q']['qty'], [4.2722, 11.3723, 14.1472, 22.8939, 36.7886, 12.3375, 0, 0, 0], 2, [t, ' : Q offer quantities'] ) t_is( co['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4, [t, ' : Q offer prices'] ) t_is( cb['Q']['qty'], [0, 0, 0, 0, 0, 0, 15, 4.0785, 5], 2, [t, ' : Q bid quantities'] ) t_is( cb['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4, [t, ' : Q bid prices'] ) t_is( co['Q']['prc'], r['bus'][[Gbus, Lbus], LAM_Q], 8, [t, ' : Q offer prices'] ) t_is( cb['Q']['prc'], co['Q']['prc'], 8, [t, ' : Q bid prices'] ) t = 'marginal Q offer, marginal PQ bid, auction_type = 0' mkt['auction_type'] = 0 r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt) t_is( co['P']['qty'], co5['P']['qty'], 8, [t, ' : gen P quantities'] ) t_is( cb['P']['qty'], cb5['P']['qty'], 8, [t, ' : load P quantities'] ) t_is( co['P']['prc'], offers['P']['prc'], 8, [t, ' : gen P prices'] ) t_is( cb['P']['prc'], bids['P']['prc'], 8, [t, ' : load P prices'] ) t_is( co['Q']['qty'], co5['Q']['qty'], 8, [t, ' : gen Q quantities'] ) t_is( cb['Q']['qty'], cb5['Q']['qty'], 8, [t, ' : load Q quantities'] ) t_is( co['Q']['prc'], offers['Q']['prc'], 8, [t, ' : gen Q prices'] ) t_is( cb['Q']['prc'], bids['Q']['prc'], 8, [t, ' : load Q prices'] ) t_end
def runpf(casedata=None, ppopt=None, fname='', solvedcase=''): """Runs a power flow. Runs a power flow [full AC Newton's method by default] and optionally returns the solved values in the data matrices, a flag which is C{True} if the algorithm was successful in finding a solution, and the elapsed time in seconds. All input arguments are optional. If C{casename} is provided it specifies the name of the input data file or dict containing the power flow data. The default value is 'case9'. If the ppopt is provided it overrides the default PYPOWER options vector and can be used to specify the solution algorithm and output options among other things. If the 3rd argument is given the pretty printed output will be appended to the file whose name is given in C{fname}. If C{solvedcase} is specified the solved case will be written to a case file in PYPOWER format with the specified name. If C{solvedcase} ends with '.mat' it saves the case as a MAT-file otherwise it saves it as a Python-file. If the C{ENFORCE_Q_LIMS} options is set to C{True} [default is false] then if any generator reactive power limit is violated after running the AC power flow, the corresponding bus is converted to a PQ bus, with Qg at the limit, and the case is re-run. The voltage magnitude at the bus will deviate from the specified value in order to satisfy the reactive power limit. If the reference bus is converted to PQ, the first remaining PV bus will be used as the slack bus for the next iteration. This may result in the real power output at this generator being slightly off from the specified values. Enforcing of generator Q limits inspired by contributions from Mu Lin, Lincoln University, New Zealand (1/14/05). @author: Ray Zimmerman (PSERC Cornell) """ ## default arguments if casedata is None: casedata = join(dirname(__file__), 'case9') ppopt = ppoption(ppopt) ## options verbose = ppopt["VERBOSE"] qlim = ppopt["ENFORCE_Q_LIMS"] ## enforce Q limits on gens? dc = ppopt["PF_DC"] ## use DC formulation? ## read data ppc = loadcase(casedata) ## add zero columns to branch for flows if needed if ppc["branch"].shape[1] < QT: ppc["branch"] = c_[ppc["branch"], zeros((ppc["branch"].shape[0], QT - ppc["branch"].shape[1] + 1))] ## convert to internal indexing ppc = ext2int(ppc) baseMVA, bus, gen, branch = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] ## get bus index lists of each type of bus ref, pv, pq = bustypes(bus, gen) ## generator info on = find(gen[:, GEN_STATUS] > 0) ## which generators are on? gbus = gen[on, GEN_BUS].astype(int) ## what buses are they at? ##----- run the power flow ----- t0 = time() if verbose > 0: v = ppver('all') stdout.write('PYPOWER Version %s, %s' % (v["Version"], v["Date"])) if dc: # DC formulation if verbose: stdout.write(' -- DC Power Flow\n') ## initial state Va0 = bus[:, VA] * (pi / 180) ## build B matrices and phase shift injections B, Bf, Pbusinj, Pfinj = makeBdc(baseMVA, bus, branch) ## compute complex bus power injections [generation - load] ## adjusted for phase shifters and real shunts Pbus = makeSbus(baseMVA, bus, gen).real - Pbusinj - bus[:, GS] / baseMVA ## "run" the power flow Va = dcpf(B, Pbus, Va0, ref, pv, pq) ## update data matrices with solution branch[:, [QF, QT]] = zeros((branch.shape[0], 2)) branch[:, PF] = (Bf * Va + Pfinj) * baseMVA branch[:, PT] = -branch[:, PF] bus[:, VM] = ones(bus.shape[0]) bus[:, VA] = Va * (180 / pi) ## update Pg for slack generator (1st gen at ref bus) ## (note: other gens at ref bus are accounted for in Pbus) ## Pg = Pinj + Pload + Gs ## newPg = oldPg + newPinj - oldPinj refgen = zeros(len(ref), dtype=int) for k in range(len(ref)): temp = find(gbus == ref[k]) refgen[k] = on[temp[0]] gen[refgen, PG] = gen[refgen, PG] + (B[ref, :] * Va - Pbus[ref]) * baseMVA success = 1 else: ## AC formulation alg = ppopt['PF_ALG'] if verbose > 0: if alg == 1: solver = 'Newton' elif alg == 2: solver = 'fast-decoupled, XB' elif alg == 3: solver = 'fast-decoupled, BX' elif alg == 4: solver = 'Gauss-Seidel' else: solver = 'unknown' print(' -- AC Power Flow (%s)\n' % solver) ## initial state # V0 = ones(bus.shape[0]) ## flat start V0 = bus[:, VM] * exp(1j * pi / 180 * bus[:, VA]) V0[gbus] = gen[on, VG] / abs(V0[gbus]) * V0[gbus] if qlim: ref0 = ref ## save index and angle of Varef0 = bus[ref0, VA] ## original reference bus(es) limited = [] ## list of indices of gens @ Q lims fixedQg = zeros(gen.shape[0]) ## Qg of gens at Q limits repeat = True while repeat: ## build admittance matrices Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch) ## compute complex bus power injections [generation - load] Sbus = makeSbus(baseMVA, bus, gen) ## run the power flow alg = ppopt["PF_ALG"] if alg == 1: V, success, _ = newtonpf(Ybus, Sbus, V0, ref, pv, pq, ppopt) elif alg == 2 or alg == 3: Bp, Bpp = makeB(baseMVA, bus, branch, alg) V, success, _ = fdpf(Ybus, Sbus, V0, Bp, Bpp, ref, pv, pq, ppopt) elif alg == 4: V, success, _ = gausspf(Ybus, Sbus, V0, ref, pv, pq, ppopt) else: stderr.write('Only Newton' 's method, fast-decoupled, and ' 'Gauss-Seidel power flow algorithms currently ' 'implemented.\n') ## update data matrices with solution bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref, pv, pq) if qlim: ## enforce generator Q limits ## find gens with violated Q constraints gen_status = gen[:, GEN_STATUS] > 0 qg_max_lim = gen[:, QG] > gen[:, QMAX] qg_min_lim = gen[:, QG] < gen[:, QMIN] mx = find(gen_status & qg_max_lim) mn = find(gen_status & qg_min_lim) if len(mx) > 0 or len( mn) > 0: ## we have some Q limit violations # No PV generators if len(pv) == 0: if verbose: if len(mx) > 0: print( 'Gen %d [only one left] exceeds upper Q limit : INFEASIBLE PROBLEM\n' % mx + 1) else: print( 'Gen %d [only one left] exceeds lower Q limit : INFEASIBLE PROBLEM\n' % mn + 1) success = 0 break ## one at a time? if qlim == 2: ## fix largest violation, ignore the rest k = argmax(r_[gen[mx, QG] - gen[mx, QMAX], gen[mn, QMIN] - gen[mn, QG]]) if k > len(mx): mn = mn[k - len(mx)] mx = [] else: mx = mx[k] mn = [] if verbose and len(mx) > 0: for i in range(len(mx)): print('Gen ' + str(mx[i] + 1) + ' at upper Q limit, converting to PQ bus\n') if verbose and len(mn) > 0: for i in range(len(mn)): print('Gen ' + str(mn[i] + 1) + ' at lower Q limit, converting to PQ bus\n') ## save corresponding limit values fixedQg[mx] = gen[mx, QMAX] fixedQg[mn] = gen[mn, QMIN] mx = r_[mx, mn].astype(int) ## convert to PQ bus gen[mx, QG] = fixedQg[mx] ## set Qg to binding for i in range( len(mx) ): ## [one at a time, since they may be at same bus] gen[mx[i], GEN_STATUS] = 0 ## temporarily turn off gen, bi = gen[mx[i], GEN_BUS] ## adjust load accordingly, bus[bi, [PD, QD]] = (bus[bi, [PD, QD]] - gen[mx[i], [PG, QG]]) if len(ref) > 1 and any(bus[gen[mx, GEN_BUS], BUS_TYPE] == REF): raise ValueError('Sorry, PYPOWER cannot enforce Q ' 'limits for slack buses in systems ' 'with multiple slacks.') bus[gen[mx, GEN_BUS].astype(int), BUS_TYPE] = PQ ## & set bus type to PQ ## update bus index lists of each type of bus ref_temp = ref ref, pv, pq = bustypes(bus, gen) if verbose and ref != ref_temp: print('Bus %d is new slack bus\n' % ref) limited = r_[limited, mx].astype(int) else: repeat = 0 ## no more generator Q limits violated else: repeat = 0 ## don't enforce generator Q limits, once is enough if qlim and len(limited) > 0: ## restore injections from limited gens [those at Q limits] gen[limited, QG] = fixedQg[limited] ## restore Qg value, for i in range( len(limited )): ## [one at a time, since they may be at same bus] bi = gen[limited[i], GEN_BUS] ## re-adjust load, bus[bi, [PD, QD]] = bus[bi, [PD, QD]] + gen[limited[i], [PG, QG]] gen[limited[i], GEN_STATUS] = 1 ## and turn gen back on if ref != ref0: ## adjust voltage angles to make original ref bus correct bus[:, VA] = bus[:, VA] - bus[ref0, VA] + Varef0 ppc["et"] = time() - t0 ppc["success"] = success ##----- output results ----- ## convert back to original bus numbering & print results ppc["bus"], ppc["gen"], ppc["branch"] = bus, gen, branch results = int2ext(ppc) ## zero out result fields of out-of-service gens & branches if len(results["order"]["gen"]["status"]["off"]) > 0: results["gen"][ix_(results["order"]["gen"]["status"]["off"], [PG, QG])] = 0 if len(results["order"]["branch"]["status"]["off"]) > 0: results["branch"][ix_(results["order"]["branch"]["status"]["off"], [PF, QF, PT, QT])] = 0 if fname: fd = None try: fd = open(fname, "a") except Exception as detail: stderr.write("Error opening %s: %s.\n" % (fname, detail)) finally: if fd is not None: printpf(results, fd, ppopt) fd.close() else: printpf(results, stdout, ppopt) ## save solved case if solvedcase: savecase(solvedcase, results) return results, success
def _runpf(casedata=None, init='flat', ac=True, Numba=True, ppopt=None): """Runs a power flow. Similar to runpf() from pypower. See Pypower documentation for more information. Changes by University of Kassel (Florian Schaefer): Numba can be used for pf calculations. Changes in structure (AC as well as DC PF can be calculated) """ ## default arguments if casedata is None: casedata = join(dirname(__file__), 'case9') ppopt = ppoption(ppopt) ## options verbose = ppopt["VERBOSE"] ## read data ppci = loadcase(casedata) # get data for calc baseMVA, bus, gen, branch = \ ppci["baseMVA"], ppci["bus"], ppci["gen"], ppci["branch"] ## get bus index lists of each type of bus ref, pv, pq = bustypes(bus, gen) ## generator info on = find(gen[:, GEN_STATUS] > 0) ## which generators are on? gbus = gen[on, GEN_BUS].astype(int) ## what buses are they at? ##----- run the power flow ----- t0 = time() if not ac or (ac and init == 'dc'): # DC formulation if verbose: print(' -- DC Power Flow\n') ## initial state Va0 = bus[:, VA] * (pi / 180) ## build B matrices and phase shift injections B, Bf, Pbusinj, Pfinj = makeBdc(baseMVA, bus, branch) ## compute complex bus power injections [generation - load] ## adjusted for phase shifters and real shunts Pbus = makeSbus(baseMVA, bus, gen) - Pbusinj - bus[:, GS] / baseMVA ## "run" the power flow Va = dcpf(B, Pbus, Va0, ref, pv, pq) ## update data matrices with solution branch[:, [QF, QT]] = zeros((branch.shape[0], 2)) branch[:, PF] = (Bf * Va + Pfinj) * baseMVA branch[:, PT] = -branch[:, PF] bus[:, VM] = ones(bus.shape[0]) bus[:, VA] = Va * (180 / pi) ## update Pg for slack generator (1st gen at ref bus) ## (note: other gens at ref bus are accounted for in Pbus) ## Pg = Pinj + Pload + Gs ## newPg = oldPg + newPinj - oldPinj refgen = zeros(len(ref), dtype=int) for k in range(len(ref)): temp = find(gbus == ref[k]) refgen[k] = on[temp[0]] gen[refgen, PG] = gen[refgen, PG] + (B[ref, :] * Va - Pbus[ref]) * baseMVA success = 1 if ac and init == 'dc': # get results from DC powerflow for AC powerflow ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch if ac: ## AC formulation # options qlim = ppopt["ENFORCE_Q_LIMS"] ## enforce Q limits on gens? ## check if numba is available and the corresponding flag try: from numba import _version as nb_version # get Numba Version (in order to use it it must be > 0.25) nbVersion = float(nb_version.version_version[:4]) if nbVersion < 0.25: print( 'Warning: Numba version too old -> Upgrade to a version > 0.25. Numba is disabled\n' ) Numba = False except ImportError: # raise UserWarning('Numba cannot be imported. Call runpp() with Numba=False!') print( 'Warning: Numba cannot be imported. Numba is disabled. Call runpp() with Numba=False!\n' ) Numba = False if Numba: from pandapower.pypower_extensions.makeYbus import makeYbus else: from pypower.makeYbus import makeYbus alg = ppopt['PF_ALG'] if verbose > 0: if alg == 1: solver = 'Newton' elif alg == 2: solver = 'fast-decoupled, XB' elif alg == 3: solver = 'fast-decoupled, BX' elif alg == 4: solver = 'Gauss-Seidel' else: solver = 'unknown' print(' -- AC Power Flow (%s)\n' % solver) ## initial state # V0 = ones(bus.shape[0]) ## flat start V0 = bus[:, VM] * exp(1j * pi / 180 * bus[:, VA]) V0[gbus] = gen[on, VG] / abs(V0[gbus]) * V0[gbus] if qlim: ref0 = ref ## save index and angle of Varef0 = bus[ref0, VA] ## original reference bus(es) limited = [] ## list of indices of gens @ Q lims fixedQg = zeros(gen.shape[0]) ## Qg of gens at Q limits repeat = True while repeat: ## build admittance matrices Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch) ## compute complex bus power injections [generation - load] Sbus = makeSbus(baseMVA, bus, gen) ## run the power flow alg = ppopt["PF_ALG"] if alg == 1: V, success, _ = newtonpf(Ybus, Sbus, V0, ref, pv, pq, ppopt, Numba) elif alg == 2 or alg == 3: Bp, Bpp = makeB(baseMVA, bus, branch, alg) V, success, _ = fdpf(Ybus, Sbus, V0, Bp, Bpp, ref, pv, pq, ppopt) elif alg == 4: V, success, _ = gausspf(Ybus, Sbus, V0, ref, pv, pq, ppopt) else: raise ValueError( 'Only Newton' 's method, fast-decoupled, and ' 'Gauss-Seidel power flow algorithms currently ' 'implemented.\n') ## update data matrices with solution bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref, pv, pq) if qlim: ## enforce generator Q limits ## find gens with violated Q constraints gen_status = gen[:, GEN_STATUS] > 0 qg_max_lim = gen[:, QG] > gen[:, QMAX] qg_min_lim = gen[:, QG] < gen[:, QMIN] mx = find(gen_status & qg_max_lim) mn = find(gen_status & qg_min_lim) if len(mx) > 0 or len( mn) > 0: ## we have some Q limit violations # No PV generators if len(pv) == 0: if verbose: if len(mx) > 0: print( 'Gen %d [only one left] exceeds upper Q limit : INFEASIBLE PROBLEM\n' % mx + 1) else: print( 'Gen %d [only one left] exceeds lower Q limit : INFEASIBLE PROBLEM\n' % mn + 1) success = 0 break ## one at a time? if qlim == 2: ## fix largest violation, ignore the rest k = argmax(r_[gen[mx, QG] - gen[mx, QMAX], gen[mn, QMIN] - gen[mn, QG]]) if k > len(mx): mn = mn[k - len(mx)] mx = [] else: mx = mx[k] mn = [] if verbose and len(mx) > 0: for i in range(len(mx)): print('Gen ' + str(mx[i] + 1) + ' at upper Q limit, converting to PQ bus\n') if verbose and len(mn) > 0: for i in range(len(mn)): print('Gen ' + str(mn[i] + 1) + ' at lower Q limit, converting to PQ bus\n') ## save corresponding limit values fixedQg[mx] = gen[mx, QMAX] fixedQg[mn] = gen[mn, QMIN] mx = r_[mx, mn].astype(int) ## convert to PQ bus gen[mx, QG] = fixedQg[mx] ## set Qg to binding for i in range( len(mx) ): ## [one at a time, since they may be at same bus] gen[mx[i], GEN_STATUS] = 0 ## temporarily turn off gen, bi = gen[mx[i], GEN_BUS] ## adjust load accordingly, bus[bi, [PD, QD]] = (bus[bi, [PD, QD]] - gen[mx[i], [PG, QG]]) if len(ref) > 1 and any(bus[gen[mx, GEN_BUS].astype(int), BUS_TYPE] == REF): raise ValueError('Sorry, PYPOWER cannot enforce Q ' 'limits for slack buses in systems ' 'with multiple slacks.') bus[gen[mx, GEN_BUS].astype(int), BUS_TYPE] = PQ ## & set bus type to PQ ## update bus index lists of each type of bus ref_temp = ref ref, pv, pq = bustypes(bus, gen) if verbose and ref != ref_temp: print('Bus %d is new slack bus\n' % ref) limited = r_[limited, mx].astype(int) else: repeat = 0 ## no more generator Q limits violated else: repeat = 0 ## don't enforce generator Q limits, once is enough if qlim and len(limited) > 0: ## restore injections from limited gens [those at Q limits] gen[limited, QG] = fixedQg[limited] ## restore Qg value, for i in range( len(limited )): ## [one at a time, since they may be at same bus] bi = gen[limited[i], GEN_BUS] ## re-adjust load, bus[bi, [PD, QD]] = bus[bi, [PD, QD]] + gen[limited[i], [PG, QG]] gen[limited[i], GEN_STATUS] = 1 ## and turn gen back on # if ref != ref0: # ## adjust voltage angles to make original ref bus correct # bus[:, VA] = bus[:, VA] - bus[ref0, VA] + Varef0 ppci["et"] = time() - t0 ppci["success"] = success ##----- output results ----- ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch results = ppci return results, success
def opf_args(*args): """Parses and initializes OPF input arguments. Returns the full set of initialized OPF input arguments, filling in default values for missing arguments. See Examples below for the possible calling syntax options. Input arguments options:: opf_args(ppc) opf_args(ppc, ppopt) opf_args(ppc, userfcn, ppopt) opf_args(ppc, A, l, u) opf_args(ppc, A, l, u, ppopt) opf_args(ppc, A, l, u, ppopt, N, fparm, H, Cw) opf_args(ppc, A, l, u, ppopt, N, fparm, H, Cw, z0, zl, zu) opf_args(baseMVA, bus, gen, branch, areas, gencost) opf_args(baseMVA, bus, gen, branch, areas, gencost, ppopt) opf_args(baseMVA, bus, gen, branch, areas, gencost, userfcn, ppopt) opf_args(baseMVA, bus, gen, branch, areas, gencost, A, l, u) opf_args(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ppopt) opf_args(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ... ppopt, N, fparm, H, Cw) opf_args(baseMVA, bus, gen, branch, areas, gencost, A, l, u, ... ppopt, N, fparm, H, Cw, z0, zl, zu) The data for the problem can be specified in one of three ways: 1. a string (ppc) containing the file name of a PYPOWER case which defines the data matrices baseMVA, bus, gen, branch, and gencost (areas is not used at all, it is only included for backward compatibility of the API). 2. a dict (ppc) containing the data matrices as fields. 3. the individual data matrices themselves. The optional user parameters for user constraints (C{A, l, u}), user costs (C{N, fparm, H, Cw}), user variable initializer (z0), and user variable limits (C{zl, zu}) can also be specified as fields in a case dict, either passed in directly or defined in a case file referenced by name. When specified, C{A, l, u} represent additional linear constraints on the optimization variables, C{l <= A*[x z] <= u}. If the user specifies an C{A} matrix that has more columns than the number of "C{x}" (OPF) variables, then there are extra linearly constrained "C{z}" variables. For an explanation of the formulation used and instructions for forming the C{A} matrix, see the MATPOWER manual. A generalized cost on all variables can be applied if input arguments C{N}, C{fparm}, C{H} and C{Cw} are specified. First, a linear transformation of the optimization variables is defined by means of C{r = N * [x z]}. Then, to each element of r a function is applied as encoded in the C{fparm} matrix (see Matpower manual). If the resulting vector is named C{w}, then C{H} and C{Cw} define a quadratic cost on C{w}: C{(1/2)*w'*H*w + Cw * w}. C{H} and C{N} should be sparse matrices and C{H} should also be symmetric. The optional C{ppopt} vector specifies PYPOWER options. See L{ppoption} for details and default values. @author: Ray Zimmerman (PSERC Cornell) @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad Autonoma de Manizales) @author: Richard Lincoln """ # nargin = len([arg for arg in [baseMVA, bus, gen, branch, areas, gencost, # Au, lbu, ubu, ppopt, N, fparm, H, Cw, # z0, zl, zu] if arg is not None]) nargin = len(args) userfcn = array([]) ## passing filename or dict if isinstance(args[0], basestring) or isinstance(args[0], dict): # ----opf( baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm, H, Cw, z0, zl, zu) # 12 opf(casefile, Au, lbu, ubu, ppopt, N, fparm, H, Cw, z0, zl, zu) # 9 opf(casefile, Au, lbu, ubu, ppopt, N, fparm, H, Cw) # 5 opf(casefile, Au, lbu, ubu, ppopt) # 4 opf(casefile, Au, lbu, ubu) # 3 opf(casefile, userfcn, ppopt) # 2 opf(casefile, ppopt) # 1 opf(casefile) if nargin in [1, 2, 3, 4, 5, 9, 12]: casefile = args[0] if nargin == 12: baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm = args zu = fparm zl = N z0 = ppopt Cw = ubu H = lbu fparm = Au N = gencost ppopt = areas ubu = branch lbu = gen Au = bus elif nargin == 9: baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu = args zu = array([]) zl = array([]) z0 = array([]) Cw = ubu H = lbu fparm = Au N = gencost ppopt = areas ubu = branch lbu = gen Au = bus elif nargin == 5: baseMVA, bus, gen, branch, areas = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = areas ubu = branch lbu = gen Au = bus elif nargin == 4: baseMVA, bus, gen, branch = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = ppoption() ubu = branch lbu = gen Au = bus elif nargin == 3: baseMVA, bus, gen = args userfcn = bus zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = gen ubu = array([]) lbu = array([]) Au = None elif nargin == 2: baseMVA, bus = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = bus ubu = array([]) lbu = array([]) Au = None elif nargin == 1: zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = ppoption() ubu = array([]) lbu = array([]) Au = None else: stderr.write('opf_args: Incorrect input arg order, number or type\n') ppc = loadcase(casefile) baseMVA, bus, gen, branch, gencost = \ ppc['baseMVA'], ppc['bus'], ppc['gen'], ppc['branch'], ppc['gencost'] if 'areas' in ppc: areas = ppc['areas'] else: areas = array([]) if Au is None and 'A' in ppc: Au, lbu, ubu = ppc["A"], ppc["l"], ppc["u"] if N is None and 'N' in ppc: ## these two must go together N, Cw = ppc["N"], ppc["Cw"] if H is None and 'H' in ppc: ## will default to zeros H = ppc["H"] if (fparm is None or len(fparm) == 0) and 'fparm' in ppc: ## will default to [1 0 0 1] fparm = ppc["fparm"] if (z0 is None or len(z0) == 0) and 'z0' in ppc: z0 = ppc["z0"] if (zl is None or len(zl) == 0) and 'zl' in ppc: zl = ppc["zl"] if (zu is None or len(zu) == 0) and 'zu' in ppc: zu = ppc["zu"] if (userfcn is None or len(userfcn) == 0) and 'userfcn' in ppc: userfcn = ppc['userfcn'] else: ## passing individual data matrices # ----opf(baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm, H, Cw, z0, zl, zu) # 17 opf(baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm, H, Cw, z0, zl, zu) # 14 opf(baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm, H, Cw) # 10 opf(baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt) # 9 opf(baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu) # 8 opf(baseMVA, bus, gen, branch, areas, gencost, userfcn, ppopt) # 7 opf(baseMVA, bus, gen, branch, areas, gencost, ppopt) # 6 opf(baseMVA, bus, gen, branch, areas, gencost) if nargin in [6, 7, 8, 9, 10, 14, 17]: if nargin == 17: baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm, H, Cw, z0, zl, zu = args elif nargin == 14: baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt, N, fparm, H, Cw = args zu = array([]) zl = array([]) z0 = array([]) elif nargin == 10: baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu, ppopt = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None elif nargin == 9: baseMVA, bus, gen, branch, areas, gencost, Au, lbu, ubu = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = ppoption() elif nargin == 8: baseMVA, bus, gen, branch, areas, gencost, userfcn, ppopt = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ubu = array([]) lbu = array([]) Au = None elif nargin == 7: baseMVA, bus, gen, branch, areas, gencost, ppopt = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ubu = array([]) lbu = array([]) Au = None elif nargin == 6: baseMVA, bus, gen, branch, areas, gencost = args zu = array([]) zl = array([]) z0 = array([]) Cw = array([]) H = None fparm = array([]) N = None ppopt = ppoption() ubu = array([]) lbu = array([]) Au = None else: stderr.write('opf_args: Incorrect input arg order, number or type\n') if N is not None: nw = N.shape[0] else: nw = 0 if nw: if Cw.shape[0] != nw: stderr.write('opf_args.m: dimension mismatch between N and Cw in ' 'generalized cost parameters\n') if len(fparm) > 0 and fparm.shape[0] != nw: stderr.write('opf_args.m: dimension mismatch between N and fparm ' 'in generalized cost parameters\n') if (H is not None) and (H.shape[0] != nw | H.shape[0] != nw): stderr.write('opf_args.m: dimension mismatch between N and H in ' 'generalized cost parameters\n') if Au is not None: if Au.shape[0] > 0 and N.shape[1] != Au.shape[1]: stderr.write('opf_args.m: A and N must have the same number ' 'of columns\n') ## make sure N and H are sparse if not issparse(N): stderr.write('opf_args.m: N must be sparse in generalized cost ' 'parameters\n') if not issparse(H): stderr.write('opf_args.m: H must be sparse in generalized cost parameters\n') if Au is not None and not issparse(Au): stderr.write('opf_args.m: Au must be sparse\n') if ppopt == None or len(ppopt) == 0: ppopt = ppoption() return baseMVA, bus, gen, branch, gencost, Au, lbu, ubu, \ ppopt, N, fparm, H, Cw, z0, zl, zu, userfcn, areas
from pypower.loadcase import loadcase import matplotlib.pyplot as plt import numpy as np if __name__ == '__main__': ######### # SETUP # ######### print('----------------------------') print('PYPOWER-Dynamics - SMIB Test') print('----------------------------') # Load PYPOWER case ppc = loadcase('smib_case.py') # Program options dynopt = {} dynopt['h'] = 0.01 # step length (s) dynopt['t_sim'] = 15 # simulation time (s) dynopt['max_err'] = 0.0001 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 50 # Nominal system frequency (Hz) # Integrator option #dynopt['iopt'] = 'mod_euler' dynopt['iopt'] = 'runge_kutta' # Create dynamic model objects
def t_opf_userfcns(quiet=False): """Tests for userfcn callbacks (reserves/iflims) w/OPF. Includes high-level tests of reserves and iflims implementations. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ t_begin(38, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case30_userfcns') verbose = 0#not quiet ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8, PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9) ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=560, OPF_ALG_DC=200) #ppopt = ppoption(ppopt, OUT_ALL=-1, VERBOSE=2, OUT_GEN=1) ## run the OPF with fixed reserves t = 'fixed reserves : ' ppc = loadcase(casefile) ppc = toggle_reserves(ppc, 'on') r = runopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'reserves.R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4, [t, 'reserves.mu.Pmax']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4, [t, 'reserves.mu.u']) t_ok('P' not in r['if'], [t, 'no iflims']) t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost']) t = 'toggle_reserves(ppc, \'off\') : '; ppc = toggle_reserves(ppc, 'off') r = runopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_ok('R' not in r['reserves'], [t, 'no reserves']) t_ok('P' not in r['if'], [t, 'no iflims']) t = 'interface flow lims (DC) : ' ppc = loadcase(casefile) ppc = toggle_iflims(ppc, 'on') r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P']) t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u']) t_is(r['branch'][13, PF], 8.244, 3, [t, 'flow in branch 14']) t_ok('R' not in r['reserves'], [t, 'no reserves']) t = 'reserves + interface flow lims (DC) : ' ppc = loadcase(casefile) ppc = toggle_reserves(ppc, 'on') ppc = toggle_iflims(ppc, 'on') r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P']) t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 38.2573], 4, [t, 'if.mu.u']) t_is(r['reserves']['R'], [25, 15, 0, 0, 16.9, 3.1], 4, [t, 'reserves.R']) t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc']) t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4, [t, 'reserves.mu.Pmax']) t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l']) t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4, [t, 'reserves.mu.u']) t_is(r['reserves']['totalcost'], 179.05, 4, [t, 'totalcost']) t = 'interface flow lims (AC) : ' ppc = toggle_reserves(ppc, 'off') r = runopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-9.101, 21.432], 3, [t, 'if.P']) t_is(r['if']['mu']['l'], [0, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 10.198], 3, [t, 'if.mu.u']) t_ok('R' not in r['reserves'], [t, 'no reserves']) t = 'interface flow lims (line out) : ' ppc = loadcase(casefile) ppc = toggle_iflims(ppc, 'on') ppc['branch'][11, BR_STATUS] = 0 ## take out line 6-10 r = rundcopf(ppc, ppopt) t_ok(r['success'], [t, 'success']) t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P']) t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l']) t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u']) t_is(r['branch'][13, PF], 10.814, 3, [t, 'flow in branch 14']) t_ok('R' not in r['reserves'], [t, 'no reserves']) # r['reserves']['R'] # r['reserves']['prc'] # r['reserves']['mu.Pmax'] # r['reserves']['mu']['l'] # r['reserves']['mu']['u'] # r['reserves']['totalcost'] # # r['if']['P'] # r['if']['mu']['l'] # r['if']['mu']['u'] t_end()
from pypower.loadcase import loadcase import matplotlib.pyplot as plt import numpy as np if __name__ == '__main__': ######### # SETUP # ######### print('-----------------------------') print('PYPOWER-Dynamics - Motor Test') print('-----------------------------') # Load PYPOWER case ppc = loadcase('test_case.py') # Program options dynopt = {} dynopt['h'] = 0.01 # step length (s) dynopt['t_sim'] = 10.0 # simulation time (s) dynopt['max_err'] = 0.0001 # Maximum error in network iteration (voltage mismatches) dynopt['max_iter'] = 25 # Maximum number of network iterations dynopt['verbose'] = False # option for verbose messages dynopt['fn'] = 50 # Nominal system frequency (Hz) # Integrator option dynopt['iopt'] = 'mod_euler' #dynopt['iopt'] = 'runge_kutta' # Create dynamic model objects