def userfcn_dcline_ext2int(ppc, args): """This is the 'ext2int' stage userfcn callback that prepares the input data for the formulation stage. It expects to find a 'dcline' field in ppc as described above. The optional args are not currently used. It adds two dummy generators for each in-service DC line, with the appropriate upper and lower generation bounds and corresponding zero-cost entries in gencost. """ c = idx_dcline.c ## initialize some things if 'dclinecost' in ppc: havecost = True else: havecost = False ## save version with external indexing ppc['order']['ext']['dcline'] = ppc['dcline'] ## external indexing if havecost: ppc['order']['ext']['dclinecost'] = ppc[ 'dclinecost'] ## external indexing ppc['order']['ext']['status'] = {} ## work with only in-service DC lines ppc['order']['ext']['status']['on'] = find( ppc['dcline'][:, c['BR_STATUS']] > 0) ppc['order']['ext']['status']['off'] = find( ppc['dcline'][:, c['BR_STATUS']] <= 0) ## remove out-of-service DC lines dc = ppc['dcline'][ppc['order']['ext']['status'] ['on'], :] ## only in-service DC lines if havecost: dcc = ppc['dclinecost'][ppc['order']['ext']['status'] ['on'], :] ## only in-service DC lines ppc['dclinecost'] = dcc ndc = dc.shape[0] ## number of in-service DC lines o = ppc['order'] ##----- convert stuff to internal indexing ----- dc[:, c['F_BUS']] = o['bus']['e2i'][dc[:, c['F_BUS']]] dc[:, c['T_BUS']] = o['bus']['e2i'][dc[:, c['T_BUS']]] ppc['dcline'] = dc ##----- create gens to represent DC line terminals ----- ## ensure consistency of initial values of PF, PT and losses ## (for simple power flow cases) dc[:, c['PT']] = dc[:, c['PF']] - (dc[:, c['LOSS0']] + dc[:, c['LOSS1']] * dc[:, c['PF']]) ## create gens fg = zeros((ndc, ppc['gen'].shape[1])) fg[:, MBASE] = 100 fg[:, GEN_STATUS] = dc[:, c['BR_STATUS']] ## status (should be all 1's) fg[:, PMIN] = -Inf fg[:, PMAX] = Inf tg = fg.copy() fg[:, GEN_BUS] = dc[:, c['F_BUS']] ## from bus tg[:, GEN_BUS] = dc[:, c['T_BUS']] ## to bus fg[:, PG] = -dc[:, c['PF']] ## flow (extracted at "from") tg[:, PG] = dc[:, c['PT']] ## flow (injected at "to") fg[:, QG] = dc[:, c['QF']] ## VAr injection at "from" tg[:, QG] = dc[:, c['QT']] ## VAr injection at "to" fg[:, VG] = dc[:, c['VF']] ## voltage set-point at "from" tg[:, VG] = dc[:, c['VT']] ## voltage set-point at "to" k = find(dc[:, c['PMIN']] >= 0) ## min positive direction flow if len(k) > 0: ## contrain at "from" end fg[k, PMAX] = -dc[k, c['PMIN']] ## "from" extraction lower lim k = find(dc[:, c['PMAX']] >= 0) ## max positive direction flow if len(k) > 0: ## contrain at "from" end fg[k, PMIN] = -dc[k, c['PMAX']] ## "from" extraction upper lim k = find(dc[:, c['PMIN']] < 0) ## max negative direction flow if len(k) > 0: ## contrain at "to" end tg[k, PMIN] = dc[k, c['PMIN']] ## "to" injection lower lim k = find(dc[:, c['PMAX']] < 0) ## min negative direction flow if len(k) > 0: ## contrain at "to" end tg[k, PMAX] = dc[k, c['PMAX']] ## "to" injection upper lim fg[:, QMIN] = dc[:, c['QMINF']] ## "from" VAr injection lower lim fg[:, QMAX] = dc[:, c['QMAXF']] ## "from" VAr injection upper lim tg[:, QMIN] = dc[:, c['QMINT']] ## "to" VAr injection lower lim tg[:, QMAX] = dc[:, c['QMAXT']] ## "to" VAr injection upper lim ## fudge PMAX a bit if necessary to avoid triggering ## dispatchable load constant power factor constraints fg[isload(fg), PMAX] = -1e-6 tg[isload(tg), PMAX] = -1e-6 ## set all terminal buses to PV (except ref bus) refbus = find(ppc['bus'][:, BUS_TYPE] == REF) ppc['bus'][dc[:, c['F_BUS']], BUS_TYPE] = PV ppc['bus'][dc[:, c['T_BUS']], BUS_TYPE] = PV ppc['bus'][refbus, BUS_TYPE] = REF ## append dummy gens ppc['gen'] = r_[ppc['gen'], fg, tg] ## gencost if 'gencost' in ppc and len(ppc['gencost']) > 0: ngcr, ngcc = ppc['gencost'].shape ## dimensions of gencost if havecost: ## user has provided costs ndccc = dcc.shape[1] ## number of dclinecost columns ccc = max(r_[ngcc, ndccc]) ## number of columns in new gencost if ccc > ngcc: ## right zero-pad gencost ppc.gencost = c_[ppc['gencost'], zeros(ngcr, ccc - ngcc)] ## flip function across vertical axis and append to gencost ## (PF for DC line = -PG for dummy gen at "from" bus) for k in range(ndc): if dcc[k, MODEL] == POLYNOMIAL: nc = dcc[k, NCOST] temp = dcc[k, NCOST + range(nc + 1)] ## flip sign on coefficients of odd terms ## (every other starting with linear term, ## that is, the next to last one) # temp((nc-1):-2:1) = -temp((nc-1):-2:1) temp[range(nc, 0, -2)] = -temp[range(nc, 0, -2)] else: ## dcc(k, MODEL) == PW_LINEAR nc = dcc[k, NCOST] temp = dcc[k, NCOST + range(2 * nc + 1)] ## switch sign on horizontal coordinate xx = -temp[range(0, 2 * nc + 1, 2)] yy = temp[range(1, 2 * nc + 1, 2)] temp[range(0, 2 * nc + 1, 2)] = xx[-1::-1] temp[range(1, 2 * nc + 1, 2)] = yy[-1::-1] padding = zeros(ccc - NCOST - len(temp)) gck = c_[dcc[k, :NCOST + 1], temp, padding] ## append to gencost ppc['gencost'] = r_[ppc['gencost'], gck] ## use zero cost on "to" end gen tgc = ones((ndc, 1)) * [2, 0, 0, 2, zeros(ccc - 4)] ppc['gencost'] = c_[ppc['gencost'], tgc] else: ## use zero cost as default dcgc = ones((2 * ndc, 1)) * concatenate( [array([2, 0, 0, 2]), zeros(ngcc - 4)]) ppc['gencost'] = r_[ppc['gencost'], dcgc] return ppc
def uopf(*args): """Solves combined unit decommitment / optimal power flow. Solves a combined unit decommitment and optimal power flow for a single time period. Uses an algorithm similar to dynamic programming. It proceeds through a sequence of stages, where stage C{N} has C{N} generators shut down, starting with C{N=0}. In each stage, it forms a list of candidates (gens at their C{Pmin} limits) and computes the cost with each one of them shut down. It selects the least cost case as the starting point for the next stage, continuing until there are no more candidates to be shut down or no more improvement can be gained by shutting something down. If C{verbose} in ppopt (see L{ppoption} is C{true}, it prints progress info, if it is > 1 it prints the output of each individual opf. @see: L{opf}, L{runuopf} @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ##----- initialization ----- t0 = time() ## start timer ## process input arguments ppc, ppopt = opf_args2(*args) ## options verbose = ppopt["VERBOSE"] if verbose: ## turn down verbosity one level for calls to opf ppopt = ppoption(ppopt, VERBOSE=verbose - 1) ##----- do combined unit commitment/optimal power flow ----- ## check for sum(Pmin) > total load, decommit as necessary on = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) ) ## gens in service onld = find( (ppc["gen"][:, GEN_STATUS] > 0) & isload(ppc["gen"]) ) ## disp loads in serv load_capacity = sum(ppc["bus"][:, PD]) - sum(ppc["gen"][onld, PMIN]) ## total load capacity Pmin = ppc["gen"][on, PMIN] while sum(Pmin) > load_capacity: ## shut down most expensive unit avgPmincost = totcost(ppc["gencost"][on, :], Pmin) / Pmin _, i = fairmax(avgPmincost) ## pick one with max avg cost at Pmin i = on[i] ## convert to generator index if verbose: print('Shutting down generator %d so all Pmin limits can be satisfied.\n' % i) ## set generation to zero ppc["gen"][i, [PG, QG, GEN_STATUS]] = 0 ## update minimum gen capacity on = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) ) ## gens in service Pmin = ppc["gen"][on, PMIN] ## run initial opf results = opf(ppc, ppopt) ## best case so far results1 = deepcopy(results) ## best case for this stage (ie. with n gens shut down, n=0,1,2 ...) results0 = deepcopy(results1) ppc["bus"] = results0["bus"].copy() ## use these V as starting point for OPF while True: ## get candidates for shutdown candidates = find((results0["gen"][:, MU_PMIN] > 0) & (results0["gen"][:, PMIN] > 0)) if len(candidates) == 0: break ## do not check for further decommitment unless we ## see something better during this stage done = True for k in candidates: ## start with best for this stage ppc["gen"] = results0["gen"].copy() ## shut down gen k ppc["gen"][k, [PG, QG, GEN_STATUS]] = 0 ## run opf results = opf(ppc, ppopt) ## something better? if results['success'] and (results["f"] < results1["f"]): results1 = deepcopy(results) k1 = k done = False ## make sure we check for further decommitment if done: ## decommits at this stage did not help, so let's quit break else: ## shutting something else down helps, so let's keep going if verbose: print('Shutting down generator %d.\n' % k1) results0 = deepcopy(results1) ppc["bus"] = results0["bus"].copy() ## use these V as starting point for OPF ## compute elapsed time et = time() - t0 ## finish preparing output results0['et'] = et return results0
def total_load(bus, gen=None, load_zone=None, which_type=None): """Returns vector of total load in each load zone. @param bus: standard C{bus} matrix with C{nb} rows, where the fixed active and reactive loads are specified in columns C{PD} and C{QD} @param gen: (optional) standard C{gen} matrix with C{ng} rows, where the dispatchable loads are specified by columns C{PG}, C{QG}, C{PMIN}, C{QMIN} and C{QMAX} (in rows for which C{isload(GEN)} returns C{True}). If C{gen} is empty, it assumes there are no dispatchable loads. @param load_zone: (optional) C{nb} element vector where the value of each element is either zero or the index of the load zone to which the corresponding bus belongs. If C{load_zone(b) = k} then the loads at bus C{b} will added to the values of C{Pd[k]} and C{Qd[k]}. If C{load_zone} is empty, the default is defined as the areas specified in the C{bus} matrix, i.e. C{load_zone = bus[:, BUS_AREA]} and load will have dimension C{= max(bus[:, BUS_AREA])}. If C{load_zone = 'all'}, the result is a scalar with the total system load. @param which_type: (default is 'BOTH' if C{gen} is provided, else 'FIXED') - 'FIXED' : sum only fixed loads - 'DISPATCHABLE' : sum only dispatchable loads - 'BOTH' : sum both fixed and dispatchable loads @see: L{scale_load} @author: Ray Zimmerman (PSERC Cornell) """ nb = bus.shape[0] ## number of buses if gen is None: gen = array([]) if load_zone is None: load_zone = array([], int) ## fill out and check which_type if len(gen) == 0: which_type = 'FIXED' if (which_type == None) and (len(gen) > 0): which_type = 'BOTH' ## 'FIXED', 'DISPATCHABLE' or 'BOTH' if (which_type[0] != 'F') and (which_type[0] != 'D') and (which_type[0] != 'B'): stderr.write("total_load: which_type should be 'FIXED, 'DISPATCHABLE or 'BOTH'\n") want_Q = True want_fixed = (which_type[0] == 'B') | (which_type[0] == 'F') want_disp = (which_type[0] == 'B') | (which_type[0] == 'D') ## initialize load_zone if isinstance(load_zone, basestring) and (load_zone == 'all'): load_zone = ones(nb, int) ## make a single zone of all buses elif len(load_zone) == 0: load_zone = bus[:, BUS_AREA].astype(int) ## use areas defined in bus data as zones nz = max(load_zone) ## number of load zones ## fixed load at each bus, & initialize dispatchable if want_fixed: Pdf = bus[:, PD] ## real power if want_Q: Qdf = bus[:, QD] ## reactive power else: Pdf = zeros(nb) ## real power if want_Q: Qdf = zeros(nb) ## reactive power ## dispatchable load at each bus if want_disp: ## need dispatchable ng = gen.shape[0] is_ld = isload(gen) & (gen[:, GEN_STATUS] > 0) ld = find(is_ld) ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1) e2i[i2e] = arange(nb) gbus = gen[:, GEN_BUS].astype(int) Cld = sparse((is_ld, (e2i[gbus], arange(ng))), (nb, ng)) Pdd = -Cld * gen[:, PMIN] ## real power if want_Q: Q = zeros(ng) Q[ld] = (gen[ld, QMIN] == 0) * gen[ld, QMAX] + \ (gen[ld, QMAX] == 0) * gen[ld, QMIN] Qdd = -Cld * Q ## reactive power else: Pdd = zeros(nb) if want_Q: Qdd = zeros(nb) ## compute load sums Pd = zeros(nz) if want_Q: Qd = zeros(nz) for k in range(1, nz + 1): idx = find(load_zone == k) Pd[k - 1] = sum(Pdf[idx]) + sum(Pdd[idx]) if want_Q: Qd[k - 1] = sum(Qdf[idx]) + sum(Qdd[idx]) return Pd, Qd
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 printpf(baseMVA, bus=None, gen=None, branch=None, f=None, success=None, et=None, fd=None, ppopt=None): """Prints power flow results. Prints power flow and optimal power flow results to C{fd} (a file descriptor which defaults to C{stdout}), with the details of what gets printed controlled by the optional C{ppopt} argument, which is a PYPOWER options vector (see L{ppoption} for details). The data can either be supplied in a single C{results} dict, or in the individual arguments: C{baseMVA}, C{bus}, C{gen}, C{branch}, C{f}, C{success} and C{et}, where C{f} is the OPF objective function value, C{success} is C{True} if the solution converged and C{False} otherwise, and C{et} is the elapsed time for the computation in seconds. If C{f} is given, it is assumed that the output is from an OPF run, otherwise it is assumed to be a simple power flow run. Examples:: ppopt = ppoptions(OUT_GEN=1, OUT_BUS=0, OUT_BRANCH=0) fd = open(fname, 'w+b') results = runopf(ppc) printpf(results) printpf(results, fd) printpf(results, fd, ppopt) printpf(baseMVA, bus, gen, branch, f, success, et) printpf(baseMVA, bus, gen, branch, f, success, et, fd) printpf(baseMVA, bus, gen, branch, f, success, et, fd, ppopt) fd.close() @author: Ray Zimmerman (PSERC Cornell) """ ##----- initialization ----- ## default arguments if isinstance(baseMVA, dict): have_results_struct = 1 results = baseMVA if gen is None: ppopt = ppoption() ## use default options else: ppopt = gen if (ppopt['OUT_ALL'] == 0): return ## nothin' to see here, bail out now if bus is None: fd = stdout ## print to stdout by default else: fd = bus baseMVA, bus, gen, branch, success, et = \ results["baseMVA"], results["bus"], results["gen"], \ results["branch"], results["success"], results["et"] if 'f' in results: f = results["f"] else: f = None else: have_results_struct = 0 if ppopt is None: ppopt = ppoption() ## use default options if fd is None: fd = stdout ## print to stdout by default if ppopt['OUT_ALL'] == 0: return ## nothin' to see here, bail out now isOPF = f is not None ## FALSE -> only simple PF data, TRUE -> OPF data ## options isDC = ppopt['PF_DC'] ## use DC formulation? OUT_ALL = ppopt['OUT_ALL'] OUT_ANY = OUT_ALL == 1 ## set to true if any pretty output is to be generated OUT_SYS_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_SYS_SUM']) OUT_AREA_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_AREA_SUM']) OUT_BUS = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BUS']) OUT_BRANCH = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BRANCH']) OUT_GEN = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_GEN']) OUT_ANY = OUT_ANY | ((OUT_ALL == -1) and (OUT_SYS_SUM or OUT_AREA_SUM or OUT_BUS or OUT_BRANCH or OUT_GEN)) if OUT_ALL == -1: OUT_ALL_LIM = ppopt['OUT_ALL_LIM'] elif OUT_ALL == 1: OUT_ALL_LIM = 2 else: OUT_ALL_LIM = 0 OUT_ANY = OUT_ANY or (OUT_ALL_LIM >= 1) if OUT_ALL_LIM == -1: OUT_V_LIM = ppopt['OUT_V_LIM'] OUT_LINE_LIM = ppopt['OUT_LINE_LIM'] OUT_PG_LIM = ppopt['OUT_PG_LIM'] OUT_QG_LIM = ppopt['OUT_QG_LIM'] else: OUT_V_LIM = OUT_ALL_LIM OUT_LINE_LIM = OUT_ALL_LIM OUT_PG_LIM = OUT_ALL_LIM OUT_QG_LIM = OUT_ALL_LIM OUT_ANY = OUT_ANY or ((OUT_ALL_LIM == -1) and (OUT_V_LIM or OUT_LINE_LIM or OUT_PG_LIM or OUT_QG_LIM)) ptol = 1e-4 ## tolerance for displaying shadow prices ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1, int) e2i[i2e] = arange(bus.shape[0]) ## sizes of things nb = bus.shape[0] ## number of buses nl = branch.shape[0] ## number of branches ng = gen.shape[0] ## number of generators ## zero out some data to make printout consistent for DC case if isDC: bus[:, r_[QD, BS]] = zeros((nb, 2)) gen[:, r_[QG, QMAX, QMIN]] = zeros((ng, 3)) branch[:, r_[BR_R, BR_B]] = zeros((nl, 2)) ## parameters ties = find(bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] != bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA]) ## area inter-ties tap = ones(nl) ## default tap ratio = 1 for lines xfmr = find(branch[:, TAP]) ## indices of transformers tap[xfmr] = branch[xfmr, TAP] ## include transformer tap ratios tap = tap * exp(1j * pi / 180 * branch[:, SHIFT]) ## add phase shifters nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0)) sorted_areas = sort(bus[:, BUS_AREA]) ## area numbers s_areas = sorted_areas[r_[1, find(diff(sorted_areas)) + 1]] nzsh = find((bus[:, GS] != 0.0) | (bus[:, BS] != 0.0)) allg = find( ~isload(gen) ) ong = find( (gen[:, GEN_STATUS] > 0) & ~isload(gen) ) onld = find( (gen[:, GEN_STATUS] > 0) & isload(gen) ) V = bus[:, VM] * exp(-1j * pi / 180 * bus[:, VA]) out = find(branch[:, BR_STATUS] == 0) ## out-of-service branches nout = len(out) if isDC: loss = zeros(nl) else: loss = baseMVA * abs(V[e2i[ branch[:, F_BUS].astype(int) ]] / tap - V[e2i[ branch[:, T_BUS].astype(int) ]])**2 / \ (branch[:, BR_R] - 1j * branch[:, BR_X]) fchg = abs(V[e2i[ branch[:, F_BUS].astype(int) ]] / tap)**2 * branch[:, BR_B] * baseMVA / 2 tchg = abs(V[e2i[ branch[:, T_BUS].astype(int) ]] )**2 * branch[:, BR_B] * baseMVA / 2 loss[out] = zeros(nout) fchg[out] = zeros(nout) tchg[out] = zeros(nout) ##----- print the stuff ----- if OUT_ANY: ## convergence & elapsed time if success: fd.write('\nConverged in %.2f seconds' % et) else: fd.write('\nDid not converge (%.2f seconds)\n' % et) ## objective function value if isOPF: fd.write('\nObjective Function Value = %.2f $/hr' % f) if OUT_SYS_SUM: fd.write('\n================================================================================') fd.write('\n| System Summary |') fd.write('\n================================================================================') fd.write('\n\nHow many? How much? P (MW) Q (MVAr)') fd.write('\n--------------------- ------------------- ------------- -----------------') fd.write('\nBuses %6d Total Gen Capacity %7.1f %7.1f to %.1f' % (nb, sum(gen[allg, PMAX]), sum(gen[allg, QMIN]), sum(gen[allg, QMAX]))) fd.write('\nGenerators %5d On-line Capacity %7.1f %7.1f to %.1f' % (len(allg), sum(gen[ong, PMAX]), sum(gen[ong, QMIN]), sum(gen[ong, QMAX]))) fd.write('\nCommitted Gens %5d Generation (actual) %7.1f %7.1f' % (len(ong), sum(gen[ong, PG]), sum(gen[ong, QG]))) fd.write('\nLoads %5d Load %7.1f %7.1f' % (len(nzld)+len(onld), sum(bus[nzld, PD])-sum(gen[onld, PG]), sum(bus[nzld, QD])-sum(gen[onld, QG]))) fd.write('\n Fixed %5d Fixed %7.1f %7.1f' % (len(nzld), sum(bus[nzld, PD]), sum(bus[nzld, QD]))) fd.write('\n Dispatchable %5d Dispatchable %7.1f of %-7.1f%7.1f' % (len(onld), -sum(gen[onld, PG]), -sum(gen[onld, PMIN]), -sum(gen[onld, QG]))) fd.write('\nShunts %5d Shunt (inj) %7.1f %7.1f' % (len(nzsh), -sum(bus[nzsh, VM]**2 * bus[nzsh, GS]), sum(bus[nzsh, VM]**2 * bus[nzsh, BS]) )) fd.write('\nBranches %5d Losses (I^2 * Z) %8.2f %8.2f' % (nl, sum(loss.real), sum(loss.imag) )) fd.write('\nTransformers %5d Branch Charging (inj) - %7.1f' % (len(xfmr), sum(fchg) + sum(tchg) )) fd.write('\nInter-ties %5d Total Inter-tie Flow %7.1f %7.1f' % (len(ties), sum(abs(branch[ties, PF]-branch[ties, PT])) / 2, sum(abs(branch[ties, QF]-branch[ties, QT])) / 2)) fd.write('\nAreas %5d' % len(s_areas)) fd.write('\n') fd.write('\n Minimum Maximum') fd.write('\n ------------------------- --------------------------------') minv = min(bus[:, VM]) mini = argmin(bus[:, VM]) maxv = max(bus[:, VM]) maxi = argmax(bus[:, VM]) fd.write('\nVoltage Magnitude %7.3f p.u. @ bus %-4d %7.3f p.u. @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) minv = min(bus[:, VA]) mini = argmin(bus[:, VA]) maxv = max(bus[:, VA]) maxi = argmax(bus[:, VA]) fd.write('\nVoltage Angle %8.2f deg @ bus %-4d %8.2f deg @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) if not isDC: maxv = max(loss.real) maxi = argmax(loss.real) fd.write('\nP Losses (I^2*R) - %8.2f MW @ line %d-%d' % (maxv, branch[maxi, F_BUS], branch[maxi, T_BUS])) maxv = max(loss.imag) maxi = argmax(loss.imag) fd.write('\nQ Losses (I^2*X) - %8.2f MVAr @ line %d-%d' % (maxv, branch[maxi, F_BUS], branch[maxi, T_BUS])) if isOPF: minv = min(bus[:, LAM_P]) mini = argmin(bus[:, LAM_P]) maxv = max(bus[:, LAM_P]) maxi = argmax(bus[:, LAM_P]) fd.write('\nLambda P %8.2f $/MWh @ bus %-4d %8.2f $/MWh @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) minv = min(bus[:, LAM_Q]) mini = argmin(bus[:, LAM_Q]) maxv = max(bus[:, LAM_Q]) maxi = argmax(bus[:, LAM_Q]) fd.write('\nLambda Q %8.2f $/MWh @ bus %-4d %8.2f $/MWh @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) fd.write('\n') if OUT_AREA_SUM: fd.write('\n================================================================================') fd.write('\n| Area Summary |') fd.write('\n================================================================================') fd.write('\nArea # of # of Gens # of Loads # of # of # of # of') fd.write('\n Num Buses Total Online Total Fixed Disp Shunt Brchs Xfmrs Ties') fd.write('\n---- ----- ----- ------ ----- ----- ----- ----- ----- ----- -----') for i in range(len(s_areas)): a = s_areas[i] ib = find(bus[:, BUS_AREA] == a) ig = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & ~isload(gen)) igon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & ~isload(gen)) ildon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & isload(gen)) inzld = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, PD], bus[:, QD])) inzsh = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, GS], bus[:, BS])) ibrch = find((bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA] == a)) in_tie = find((bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA] != a)) out_tie = find((bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] != a) & (bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA] == a)) if not any(xfmr + 1): nxfmr = 0 else: nxfmr = len(find((bus[e2i[branch[xfmr, F_BUS].astype(int)], BUS_AREA] == a) & (bus[e2i[branch[xfmr, T_BUS].astype(int)], BUS_AREA] == a))) fd.write('\n%3d %6d %5d %5d %5d %5d %5d %5d %5d %5d %5d' % (a, len(ib), len(ig), len(igon), \ len(inzld)+len(ildon), len(inzld), len(ildon), \ len(inzsh), len(ibrch), nxfmr, len(in_tie)+len(out_tie))) fd.write('\n---- ----- ----- ------ ----- ----- ----- ----- ----- ----- -----') fd.write('\nTot: %6d %5d %5d %5d %5d %5d %5d %5d %5d %5d' % (nb, len(allg), len(ong), len(nzld)+len(onld), len(nzld), len(onld), len(nzsh), nl, len(xfmr), len(ties))) fd.write('\n') fd.write('\nArea Total Gen Capacity On-line Gen Capacity Generation') fd.write('\n Num MW MVAr MW MVAr MW MVAr') fd.write('\n---- ------ ------------------ ------ ------------------ ------ ------') for i in range(len(s_areas)): a = s_areas[i] ig = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & ~isload(gen)) igon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & ~isload(gen)) fd.write('\n%3d %7.1f %7.1f to %-7.1f %7.1f %7.1f to %-7.1f %7.1f %7.1f' % (a, sum(gen[ig, PMAX]), sum(gen[ig, QMIN]), sum(gen[ig, QMAX]), sum(gen[igon, PMAX]), sum(gen[igon, QMIN]), sum(gen[igon, QMAX]), sum(gen[igon, PG]), sum(gen[igon, QG]) )) fd.write('\n---- ------ ------------------ ------ ------------------ ------ ------') fd.write('\nTot: %7.1f %7.1f to %-7.1f %7.1f %7.1f to %-7.1f %7.1f %7.1f' % (sum(gen[allg, PMAX]), sum(gen[allg, QMIN]), sum(gen[allg, QMAX]), sum(gen[ong, PMAX]), sum(gen[ong, QMIN]), sum(gen[ong, QMAX]), sum(gen[ong, PG]), sum(gen[ong, QG]) )) fd.write('\n') fd.write('\nArea Disp Load Cap Disp Load Fixed Load Total Load') fd.write('\n Num MW MVAr MW MVAr MW MVAr MW MVAr') fd.write('\n---- ------ ------ ------ ------ ------ ------ ------ ------') Qlim = (gen[:, QMIN] == 0) * gen[:, QMAX] + (gen[:, QMAX] == 0) * gen[:, QMIN] for i in range(len(s_areas)): a = s_areas[i] ildon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & isload(gen)) inzld = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, PD], bus[:, QD])) fd.write('\n%3d %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f' % (a, -sum(gen[ildon, PMIN]), -sum(Qlim[ildon]), -sum(gen[ildon, PG]), -sum(gen[ildon, QG]), sum(bus[inzld, PD]), sum(bus[inzld, QD]), -sum(gen[ildon, PG]) + sum(bus[inzld, PD]), -sum(gen[ildon, QG]) + sum(bus[inzld, QD]) )) fd.write('\n---- ------ ------ ------ ------ ------ ------ ------ ------') fd.write('\nTot: %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f' % (-sum(gen[onld, PMIN]), -sum(Qlim[onld]), -sum(gen[onld, PG]), -sum(gen[onld, QG]), sum(bus[nzld, PD]), sum(bus[nzld, QD]), -sum(gen[onld, PG]) + sum(bus[nzld, PD]), -sum(gen[onld, QG]) + sum(bus[nzld, QD])) ) fd.write('\n') fd.write('\nArea Shunt Inj Branch Series Losses Net Export') fd.write('\n Num MW MVAr Charging MW MVAr MW MVAr') fd.write('\n---- ------ ------ -------- ------ ------ ------ ------') for i in range(len(s_areas)): a = s_areas[i] inzsh = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, GS], bus[:, BS])) ibrch = find((bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA] == a) & branch[:, BR_STATUS].astype(bool)) in_tie = find((bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] != a) & (bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA] == a) & branch[:, BR_STATUS].astype(bool)) out_tie = find((bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA] != a) & branch[:, BR_STATUS].astype(bool)) fd.write('\n%3d %7.1f %7.1f %7.1f %7.2f %7.2f %7.1f %7.1f' % (a, -sum(bus[inzsh, VM]**2 * bus[inzsh, GS]), sum(bus[inzsh, VM]**2 * bus[inzsh, BS]), sum(fchg[ibrch]) + sum(tchg[ibrch]) + sum(fchg[out_tie]) + sum(tchg[in_tie]), sum(real(loss[ibrch])) + sum(real(loss[r_[in_tie, out_tie]])) / 2, sum(imag(loss[ibrch])) + sum(imag(loss[r_[in_tie, out_tie]])) / 2, sum(branch[in_tie, PT])+sum(branch[out_tie, PF]) - sum(real(loss[r_[in_tie, out_tie]])) / 2, sum(branch[in_tie, QT])+sum(branch[out_tie, QF]) - sum(imag(loss[r_[in_tie, out_tie]])) / 2 )) fd.write('\n---- ------ ------ -------- ------ ------ ------ ------') fd.write('\nTot: %7.1f %7.1f %7.1f %7.2f %7.2f - -' % (-sum(bus[nzsh, VM]**2 * bus[nzsh, GS]), sum(bus[nzsh, VM]**2 * bus[nzsh, BS]), sum(fchg) + sum(tchg), sum(real(loss)), sum(imag(loss)) )) fd.write('\n') ## generator data if OUT_GEN: if isOPF: genlamP = bus[e2i[gen[:, GEN_BUS].astype(int)], LAM_P] genlamQ = bus[e2i[gen[:, GEN_BUS].astype(int)], LAM_Q] fd.write('\n================================================================================') fd.write('\n| Generator Data |') fd.write('\n================================================================================') fd.write('\n Gen Bus Status Pg Qg ') if isOPF: fd.write(' Lambda ($/MVA-hr)') fd.write('\n # # (MW) (MVAr) ') if isOPF: fd.write(' P Q ') fd.write('\n---- ----- ------ -------- --------') if isOPF: fd.write(' -------- --------') for k in range(len(ong)): i = ong[k] fd.write('\n%3d %6d %2d ' % (i, gen[i, GEN_BUS], gen[i, GEN_STATUS])) if (gen[i, GEN_STATUS] > 0) & logical_or(gen[i, PG], gen[i, QG]): fd.write('%10.2f%10.2f' % (gen[i, PG], gen[i, QG])) else: fd.write(' - - ') if isOPF: fd.write('%10.2f%10.2f' % (genlamP[i], genlamQ[i])) fd.write('\n -------- --------') fd.write('\n Total: %9.2f%10.2f' % (sum(gen[ong, PG]), sum(gen[ong, QG]))) fd.write('\n') if any(onld + 1): fd.write('\n================================================================================') fd.write('\n| Dispatchable Load Data |') fd.write('\n================================================================================') fd.write('\n Gen Bus Status Pd Qd ') if isOPF: fd.write(' Lambda ($/MVA-hr)') fd.write('\n # # (MW) (MVAr) ') if isOPF: fd.write(' P Q ') fd.write('\n---- ----- ------ -------- --------') if isOPF: fd.write(' -------- --------') for k in range(len(onld)): i = onld[k] fd.write('\n%3d %6d %2d ' % (i, gen[i, GEN_BUS], gen[i, GEN_STATUS])) if (gen[i, GEN_STATUS] > 0) & logical_or(gen[i, PG], gen[i, QG]): fd.write('%10.2f%10.2f' % (-gen[i, PG], -gen[i, QG])) else: fd.write(' - - ') if isOPF: fd.write('%10.2f%10.2f' % (genlamP[i], genlamQ[i])) fd.write('\n -------- --------') fd.write('\n Total: %9.2f%10.2f' % (-sum(gen[onld, PG]), -sum(gen[onld, QG]))) fd.write('\n') ## bus data if OUT_BUS: fd.write('\n================================================================================') fd.write('\n| Bus Data |') fd.write('\n================================================================================') fd.write('\n Bus Voltage Generation Load ') if isOPF: fd.write(' Lambda($/MVA-hr)') fd.write('\n # Mag(pu) Ang(deg) P (MW) Q (MVAr) P (MW) Q (MVAr)') if isOPF: fd.write(' P Q ') fd.write('\n----- ------- -------- -------- -------- -------- --------') if isOPF: fd.write(' ------- -------') for i in range(nb): fd.write('\n%5d%7.3f%9.3f' % tuple(bus[i, [BUS_I, VM, VA]])) if bus[i, BUS_TYPE] == REF: fd.write('*') else: fd.write(' ') g = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & ~isload(gen)) ld = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & isload(gen)) if any(g + 1): fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG]))) else: fd.write(' - - ') if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1): if any(ld + 1): fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]), bus[i, QD] - sum(gen[ld, QG]))) else: fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]])) else: fd.write(' - - ') if isOPF: fd.write('%9.3f' % bus[i, LAM_P]) if abs(bus[i, LAM_Q]) > ptol: fd.write('%8.3f' % bus[i, LAM_Q]) else: fd.write(' -') fd.write('\n -------- -------- -------- --------') fd.write('\n Total: %9.2f %9.2f %9.2f %9.2f' % (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) - sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG]))) fd.write('\n') ## branch data if OUT_BRANCH: fd.write('\n================================================================================') fd.write('\n| Branch Data |') fd.write('\n================================================================================') fd.write('\nBrnch From To From Bus Injection To Bus Injection Loss (I^2 * Z) ') fd.write('\n # Bus Bus P (MW) Q (MVAr) P (MW) Q (MVAr) P (MW) Q (MVAr)') fd.write('\n----- ----- ----- -------- -------- -------- -------- -------- --------') for i in range(nl): fd.write('\n%4d%7d%7d%10.2f%10.2f%10.2f%10.2f%10.3f%10.2f' % (i, branch[i, F_BUS], branch[i, T_BUS], branch[i, PF], branch[i, QF], branch[i, PT], branch[i, QT], loss[i].real, loss[i].imag)) fd.write('\n -------- --------') fd.write('\n Total:%10.3f%10.2f' % (sum(real(loss)), sum(imag(loss)))) fd.write('\n') ##----- constraint data ----- if isOPF: ctol = ppopt['OPF_VIOLATION'] ## constraint violation tolerance ## voltage constraints if (not isDC) & (OUT_V_LIM == 2 | (OUT_V_LIM == 1 & (any(bus[:, VM] < bus[:, VMIN] + ctol) | any(bus[:, VM] > bus[:, VMAX] - ctol) | any(bus[:, MU_VMIN] > ptol) | any(bus[:, MU_VMAX] > ptol)))): fd.write('\n================================================================================') fd.write('\n| Voltage Constraints |') fd.write('\n================================================================================') fd.write('\nBus # Vmin mu Vmin |V| Vmax Vmax mu') fd.write('\n----- -------- ----- ----- ----- --------') for i in range(nb): if (OUT_V_LIM == 2) | (OUT_V_LIM == 1 & ((bus[i, VM] < bus[i, VMIN] + ctol) | (bus[i, VM] > bus[i, VMAX] - ctol) | (bus[i, MU_VMIN] > ptol) | (bus[i, MU_VMAX] > ptol))): fd.write('\n%5d' % bus[i, BUS_I]) if ((bus[i, VM] < bus[i, VMIN] + ctol) | (bus[i, MU_VMIN] > ptol)): fd.write('%10.3f' % bus[i, MU_VMIN]) else: fd.write(' - ') fd.write('%8.3f%7.3f%7.3f' % tuple(bus[i, [VMIN, VM, VMAX]])) if (bus[i, VM] > bus[i, VMAX] - ctol) | (bus[i, MU_VMAX] > ptol): fd.write('%10.3f' % bus[i, MU_VMAX]) else: fd.write(' - ') fd.write('\n') ## generator P constraints if (OUT_PG_LIM == 2) | \ ((OUT_PG_LIM == 1) & (any(gen[ong, PG] < gen[ong, PMIN] + ctol) | any(gen[ong, PG] > gen[ong, PMAX] - ctol) | any(gen[ong, MU_PMIN] > ptol) | any(gen[ong, MU_PMAX] > ptol))) | \ ((not isDC) & ((OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & (any(gen[ong, QG] < gen[ong, QMIN] + ctol) | any(gen[ong, QG] > gen[ong, QMAX] - ctol) | any(gen[ong, MU_QMIN] > ptol) | any(gen[ong, MU_QMAX] > ptol))))): fd.write('\n================================================================================') fd.write('\n| Generation Constraints |') fd.write('\n================================================================================') if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) & (any(gen[ong, PG] < gen[ong, PMIN] + ctol) | any(gen[ong, PG] > gen[ong, PMAX] - ctol) | any(gen[ong, MU_PMIN] > ptol) | any(gen[ong, MU_PMAX] > ptol))): fd.write('\n Gen Bus Active Power Limits') fd.write('\n # # Pmin mu Pmin Pg Pmax Pmax mu') fd.write('\n---- ----- ------- -------- -------- -------- -------') for k in range(len(ong)): i = ong[k] if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) & ((gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMIN] > ptol) | (gen[i, MU_PMAX] > ptol))): fd.write('\n%4d%6d ' % (i, gen[i, GEN_BUS])) if (gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, MU_PMIN] > ptol): fd.write('%8.3f' % gen[i, MU_PMIN]) else: fd.write(' - ') if gen[i, PG]: fd.write('%10.2f%10.2f%10.2f' % tuple(gen[i, [PMIN, PG, PMAX]])) else: fd.write('%10.2f - %10.2f' % tuple(gen[i, [PMIN, PMAX]])) if (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMAX] > ptol): fd.write('%9.3f' % gen[i, MU_PMAX]) else: fd.write(' - ') fd.write('\n') ## generator Q constraints if (not isDC) & ((OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & (any(gen[ong, QG] < gen[ong, QMIN] + ctol) | any(gen[ong, QG] > gen[ong, QMAX] - ctol) | any(gen[ong, MU_QMIN] > ptol) | any(gen[ong, MU_QMAX] > ptol)))): fd.write('\nGen Bus Reactive Power Limits') fd.write('\n # # Qmin mu Qmin Qg Qmax Qmax mu') fd.write('\n--- --- ------- -------- -------- -------- -------') for k in range(len(ong)): i = ong[k] if (OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & ((gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMIN] > ptol) | (gen[i, MU_QMAX] > ptol))): fd.write('\n%3d%5d' % (i, gen[i, GEN_BUS])) if (gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, MU_QMIN] > ptol): fd.write('%8.3f' % gen[i, MU_QMIN]) else: fd.write(' - ') if gen[i, QG]: fd.write('%10.2f%10.2f%10.2f' % tuple(gen[i, [QMIN, QG, QMAX]])) else: fd.write('%10.2f - %10.2f' % tuple(gen[i, [QMIN, QMAX]])) if (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMAX] > ptol): fd.write('%9.3f' % gen[i, MU_QMAX]) else: fd.write(' - ') fd.write('\n') ## dispatchable load P constraints if (OUT_PG_LIM == 2) | (OUT_QG_LIM == 2) | \ ((OUT_PG_LIM == 1) & (any(gen[onld, PG] < gen[onld, PMIN] + ctol) | any(gen[onld, PG] > gen[onld, PMAX] - ctol) | any(gen[onld, MU_PMIN] > ptol) | any(gen[onld, MU_PMAX] > ptol))) | \ ((OUT_QG_LIM == 1) & (any(gen[onld, QG] < gen[onld, QMIN] + ctol) | any(gen[onld, QG] > gen[onld, QMAX] - ctol) | any(gen[onld, MU_QMIN] > ptol) | any(gen[onld, MU_QMAX] > ptol))): fd.write('\n================================================================================') fd.write('\n| Dispatchable Load Constraints |') fd.write('\n================================================================================') if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) & (any(gen[onld, PG] < gen[onld, PMIN] + ctol) | any(gen[onld, PG] > gen[onld, PMAX] - ctol) | any(gen[onld, MU_PMIN] > ptol) | any(gen[onld, MU_PMAX] > ptol))): fd.write('\nGen Bus Active Power Limits') fd.write('\n # # Pmin mu Pmin Pg Pmax Pmax mu') fd.write('\n--- --- ------- -------- -------- -------- -------') for k in range(len(onld)): i = onld[k] if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) & ((gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMIN] > ptol) | (gen[i, MU_PMAX] > ptol))): fd.write('\n%3d%5d' % (i, gen[i, GEN_BUS])) if (gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, MU_PMIN] > ptol): fd.write('%8.3f' % gen[i, MU_PMIN]) else: fd.write(' - ') if gen[i, PG]: fd.write('%10.2f%10.2f%10.2f' % gen[i, [PMIN, PG, PMAX]]) else: fd.write('%10.2f - %10.2f' % gen[i, [PMIN, PMAX]]) if (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMAX] > ptol): fd.write('%9.3f' % gen[i, MU_PMAX]) else: fd.write(' - ') fd.write('\n') ## dispatchable load Q constraints if (not isDC) & ((OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & (any(gen[onld, QG] < gen[onld, QMIN] + ctol) | any(gen[onld, QG] > gen[onld, QMAX] - ctol) | any(gen[onld, MU_QMIN] > ptol) | any(gen[onld, MU_QMAX] > ptol)))): fd.write('\nGen Bus Reactive Power Limits') fd.write('\n # # Qmin mu Qmin Qg Qmax Qmax mu') fd.write('\n--- --- ------- -------- -------- -------- -------') for k in range(len(onld)): i = onld[k] if (OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & ((gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMIN] > ptol) | (gen[i, MU_QMAX] > ptol))): fd.write('\n%3d%5d' % (i, gen(i, GEN_BUS))) if (gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, MU_QMIN] > ptol): fd.write('%8.3f' % gen[i, MU_QMIN]) else: fd.write(' - ') if gen[i, QG]: fd.write('%10.2f%10.2f%10.2f' % gen[i, [QMIN, QG, QMAX]]) else: fd.write('%10.2f - %10.2f' % gen[i, [QMIN, QMAX]]) if (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMAX] > ptol): fd.write('%9.3f' % gen[i, MU_QMAX]) else: fd.write(' - ') fd.write('\n') ## line flow constraints if (ppopt['OPF_FLOW_LIM'] == 1) | isDC: ## P limit Ff = branch[:, PF] Ft = branch[:, PT] strg = '\n # Bus Pf mu Pf |Pmax| Pt Pt mu Bus' elif ppopt['OPF_FLOW_LIM'] == 2: ## |I| limit Ff = abs( (branch[:, PF] + 1j * branch[:, QF]) / V[e2i[branch[:, F_BUS].astype(int)]] ) Ft = abs( (branch[:, PT] + 1j * branch[:, QT]) / V[e2i[branch[:, T_BUS].astype(int)]] ) strg = '\n # Bus |If| mu |If| |Imax| |It| |It| mu Bus' else: ## |S| limit Ff = abs(branch[:, PF] + 1j * branch[:, QF]) Ft = abs(branch[:, PT] + 1j * branch[:, QT]) strg = '\n # Bus |Sf| mu |Sf| |Smax| |St| |St| mu Bus' if (OUT_LINE_LIM == 2) | ((OUT_LINE_LIM == 1) & (any((branch[:, RATE_A] != 0) & (abs(Ff) > branch[:, RATE_A] - ctol)) | any((branch[:, RATE_A] != 0) & (abs(Ft) > branch[:, RATE_A] - ctol)) | any(branch[:, MU_SF] > ptol) | any(branch[:, MU_ST] > ptol))): fd.write('\n================================================================================') fd.write('\n| Branch Flow Constraints |') fd.write('\n================================================================================') fd.write('\nBrnch From "From" End Limit "To" End To') fd.write(strg) fd.write('\n----- ----- ------- -------- -------- -------- ------- -----') for i in range(nl): if (OUT_LINE_LIM == 2) | ((OUT_LINE_LIM == 1) & (((branch[i, RATE_A] != 0) & (abs(Ff[i]) > branch[i, RATE_A] - ctol)) | ((branch[i, RATE_A] != 0) & (abs(Ft[i]) > branch[i, RATE_A] - ctol)) | (branch[i, MU_SF] > ptol) | (branch[i, MU_ST] > ptol))): fd.write('\n%4d%7d' % (i, branch[i, F_BUS])) if (Ff[i] > branch[i, RATE_A] - ctol) | (branch[i, MU_SF] > ptol): fd.write('%10.3f' % branch[i, MU_SF]) else: fd.write(' - ') fd.write('%9.2f%10.2f%10.2f' % (Ff[i], branch[i, RATE_A], Ft[i])) if (Ft[i] > branch[i, RATE_A] - ctol) | (branch[i, MU_ST] > ptol): fd.write('%10.3f' % branch[i, MU_ST]) else: fd.write(' - ') fd.write('%6d' % branch[i, T_BUS]) fd.write('\n') ## execute userfcn callbacks for 'printpf' stage if have_results_struct and 'userfcn' in results: if not isOPF: ## turn off option for all constraints if it isn't an OPF ppopt = ppoption(ppopt, 'OUT_ALL_LIM', 0) run_userfcn(results["userfcn"], 'printpf', results, fd, ppopt)
def total_load(bus, gen=None, load_zone=None, which_type=None): """Returns vector of total load in each load zone. @param bus: standard C{bus} matrix with C{nb} rows, where the fixed active and reactive loads are specified in columns C{PD} and C{QD} @param gen: (optional) standard C{gen} matrix with C{ng} rows, where the dispatchable loads are specified by columns C{PG}, C{QG}, C{PMIN}, C{QMIN} and C{QMAX} (in rows for which C{isload(GEN)} returns C{True}). If C{gen} is empty, it assumes there are no dispatchable loads. @param load_zone: (optional) C{nb} element vector where the value of each element is either zero or the index of the load zone to which the corresponding bus belongs. If C{load_zone(b) = k} then the loads at bus C{b} will added to the values of C{Pd[k]} and C{Qd[k]}. If C{load_zone} is empty, the default is defined as the areas specified in the C{bus} matrix, i.e. C{load_zone = bus[:, BUS_AREA]} and load will have dimension C{= max(bus[:, BUS_AREA])}. If C{load_zone = 'all'}, the result is a scalar with the total system load. @param which_type: (default is 'BOTH' if C{gen} is provided, else 'FIXED') - 'FIXED' : sum only fixed loads - 'DISPATCHABLE' : sum only dispatchable loads - 'BOTH' : sum both fixed and dispatchable loads @see: L{scale_load} @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ nb = bus.shape[0] ## number of buses if gen is None: gen = array([]) if load_zone is None: load_zone = array([], int) ## fill out and check which_type if len(gen) == 0: which_type = 'FIXED' if (which_type == None) and (len(gen) > 0): which_type = 'BOTH' ## 'FIXED', 'DISPATCHABLE' or 'BOTH' if (which_type[0] != 'F') and (which_type[0] != 'D') and (which_type[0] != 'B'): stderr.write("total_load: which_type should be 'FIXED, 'DISPATCHABLE or 'BOTH'\n") want_Q = True want_fixed = (which_type[0] == 'B') | (which_type[0] == 'F') want_disp = (which_type[0] == 'B') | (which_type[0] == 'D') ## initialize load_zone if isinstance(load_zone, basestring) and (load_zone == 'all'): load_zone = ones(nb, int) ## make a single zone of all buses elif len(load_zone) == 0: load_zone = bus[:, BUS_AREA].astype(int) ## use areas defined in bus data as zones nz = max(load_zone) ## number of load zones ## fixed load at each bus, & initialize dispatchable if want_fixed: Pdf = bus[:, PD] ## real power if want_Q: Qdf = bus[:, QD] ## reactive power else: Pdf = zeros(nb) ## real power if want_Q: Qdf = zeros(nb) ## reactive power ## dispatchable load at each bus if want_disp: ## need dispatchable ng = gen.shape[0] is_ld = isload(gen) and (gen[:, GEN_STATUS] > 0) ld = find(is_ld) ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1) e2i[i2e] = arange(nb) gbus = gen[:, GEN_BUS].astype(int) Cld = sparse((is_ld, (e2i[gbus], arange(ng))), (nb, ng)) Pdd = -Cld * gen[:, PMIN] ## real power if want_Q: Q = zeros(ng) Q[ld] = (gen[ld, QMIN] == 0) * gen[ld, QMAX] + \ (gen[ld, QMAX] == 0) * gen[ld, QMIN] Qdd = -Cld * Q ## reactive power else: Pdd = zeros(nb) if want_Q: Qdd = zeros(nb) ## compute load sums Pd = zeros(nz) if want_Q: Qd = zeros(nz) for k in range(1, nz + 1): idx = find(load_zone == k) Pd[k - 1] = sum(Pdf[idx]) + sum(Pdd[idx]) if want_Q: Qd[k - 1] = sum(Qdf[idx]) + sum(Qdd[idx]) return Pd, Qd
def uopf(*args): """Solves combined unit decommitment / optimal power flow. Solves a combined unit decommitment and optimal power flow for a single time period. Uses an algorithm similar to dynamic programming. It proceeds through a sequence of stages, where stage C{N} has C{N} generators shut down, starting with C{N=0}. In each stage, it forms a list of candidates (gens at their C{Pmin} limits) and computes the cost with each one of them shut down. It selects the least cost case as the starting point for the next stage, continuing until there are no more candidates to be shut down or no more improvement can be gained by shutting something down. If C{verbose} in ppopt (see L{ppoption} is C{true}, it prints progress info, if it is > 1 it prints the output of each individual opf. @see: L{opf}, L{runuopf} @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ##----- initialization ----- t0 = time() ## start timer ## process input arguments ppc, ppopt = opf_args2(*args) ## options verbose = ppopt["VERBOSE"] if verbose: ## turn down verbosity one level for calls to opf ppopt = ppoption(ppopt, VERBOSE=verbose - 1) ##----- do combined unit commitment/optimal power flow ----- ## check for sum(Pmin) > total load, decommit as necessary on = find((ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"])) ## gens in service onld = find((ppc["gen"][:, GEN_STATUS] > 0) & isload(ppc["gen"])) ## disp loads in serv load_capacity = sum(ppc["bus"][:, PD]) - sum( ppc["gen"][onld, PMIN]) ## total load capacity Pmin = ppc["gen"][on, PMIN] while sum(Pmin) > load_capacity: ## shut down most expensive unit avgPmincost = totcost(ppc["gencost"][on, :], Pmin) / Pmin _, i = fairmax(avgPmincost) ## pick one with max avg cost at Pmin i = on[i] ## convert to generator index if verbose: print( 'Shutting down generator %d so all Pmin limits can be satisfied.\n' % i) ## set generation to zero ppc["gen"][i, [PG, QG, GEN_STATUS]] = 0 ## update minimum gen capacity on = find((ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"])) ## gens in service Pmin = ppc["gen"][on, PMIN] ## run initial opf results = opf(ppc, ppopt) ## best case so far results1 = deepcopy(results) ## best case for this stage (ie. with n gens shut down, n=0,1,2 ...) results0 = deepcopy(results1) ppc["bus"] = results0["bus"].copy( ) ## use these V as starting point for OPF while True: ## get candidates for shutdown candidates = find((results0["gen"][:, MU_PMIN] > 0) & (results0["gen"][:, PMIN] > 0)) if len(candidates) == 0: break ## do not check for further decommitment unless we ## see something better during this stage done = True for k in candidates: ## start with best for this stage ppc["gen"] = results0["gen"].copy() ## shut down gen k ppc["gen"][k, [PG, QG, GEN_STATUS]] = 0 ## run opf results = opf(ppc, ppopt) ## something better? if results['success'] and (results["f"] < results1["f"]): results1 = deepcopy(results) k1 = k done = False ## make sure we check for further decommitment if done: ## decommits at this stage did not help, so let's quit break else: ## shutting something else down helps, so let's keep going if verbose: print('Shutting down generator %d.\n' % k1) results0 = deepcopy(results1) ppc["bus"] = results0["bus"].copy( ) ## use these V as starting point for OPF ## compute elapsed time et = time() - t0 ## finish preparing output results0['et'] = et return results0
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 t_off2case(quiet=False): """Tests for code in C{off2case}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ n_tests = 35 t_begin(n_tests, quiet) ## generator data # bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf gen0 = array([ [1, 10, 0, 60, -15, 1, 100, 1, 60, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 10, 0, 60, -15, 1, 100, 1, 60, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [7, -30, -15, 0, -15, 1, 100, 1, 0, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [13, 10, 0, 60, -15, 1, 100, 1, 60, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [30, -30, 7.5, 7.5, 0, 1, 100, 1, 0, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ], float) ## generator cost data # 1 startup shutdown n x1 y1 ... xn yn # 2 startup shutdown n c(n-1) ... c0 gencost0 = array([ [1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 100, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 0, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 50, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000] ], float) try: from pypower.extras.smartmarket import off2case except ImportError: t_skip(n_tests, 'smartmarket code not available') return t = 'isload()' t_is(isload(gen0), array([0, 0, 1, 0, 1], bool), 8, t) G = find( ~isload(gen0) ) L = find( isload(gen0) ) nGL = len(G) + len(L) t = 'P offers only'; offers = {'P': {}} offers['P']['qty'] = array([[25], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) gen, gencost = off2case(gen0, gencost0, offers) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'].flatten() gen1[L, GEN_STATUS] = 0 t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0.copy() gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700], ]), zeros((3, 4))] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) offers['P']['qty'] = array([[25], [26], [0], [27], [0]], float) offers['P']['prc'] = array([[10], [50], [0], [100], [0]], float) gen, gencost = off2case(gen0, gencost0, offers) t_is( gen, gen1, 8, [t, ' (all rows in offer) - gen'] ) t_is( gencost, gencost1, 8, [t, ' (all rows in offer) - gencost'] ) t = 'P offers only (GEN_STATUS=0 for 0 qty offer)'; offers['P']['qty'] = array([ [0], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) gen, gencost = off2case(gen0, gencost0, offers) gen1 = gen0.copy() gen1[G[1:3], PMAX] = offers['P']['qty'].flatten()[1:3] gen1[G[0], GEN_STATUS] = 0 gen1[L, GEN_STATUS] = 0 t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0.copy() gencost1[ix_(G[1:3], range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700] ]), zeros((2, 4))] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers, lim[\'P\'][\'max_offer\']'; offers['P']['qty'] = array([[25], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) lim = {'P': {'max_offer': 75}} gen, gencost = off2case(gen0, gencost0, offers, lim=lim) gen1 = gen0.copy() gen1[G[:2], PMAX] = offers['P']['qty'].flatten()[:2, :] gen1[r_[G[2], L], GEN_STATUS] = 0 t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0.copy() gencost1[ix_(G[:2], range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300] ]), zeros((2, 4))] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers & P bids'; bids = {'P': {'qty': array([ [20], [28]], float), 'prc': array([[100], [10]], float)}} gen, gencost = off2case(gen0, gencost0, offers, bids) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([ [-20, -10, 0], [-28, 0, 7] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :8].copy() gencost1[ix_(G, range(NCOST, NCOST + 4))] = array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700] ]) gencost1[ix_(L, range(NCOST, NCOST + 4))] = array([ [2, -20, -2000, 0, 0], [2, -28, -280, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers & P bids (all rows in bid)'; bids['P']['qty'] = array([[0], [0], [20], [0], [28]], float) bids['P']['prc'] = array([[0], [0], [100], [0], [10]], float) gen, gencost = off2case(gen0, gencost0, offers, bids) t_is( gen, gen1, 8, [t, ' - gen'] ) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers & P bids (GEN_STATUS=0 for 0 qty bid)'; bids['P']['qty'] = array([ [0], [28]], float) bids['P']['prc'] = array([[100], [10]], float) gen, gencost = off2case(gen0, gencost0, offers, bids) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[L[0], GEN_STATUS] = 0 gen1[L[1], [PMIN, QMIN, QMAX]] = array([-28, 0, 7]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0.copy() gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700] ]), zeros((3, 4))] gencost1[L[1], NCOST:NCOST + 8] = c_[array([ [2, -28, -280, 0, 0] ]), zeros((1, 4))] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers & P bids (1 gen with both)'; gen2 = gen0.copy() gen2[1, PMIN] = -5 bids['P']['qty'] = array([[0], [3], [20], [0], [28]], float) bids['P']['prc'] = array([[0], [50], [100], [0], [10]], float) gen, gencost = off2case(gen2, gencost0, offers, bids) gen1 = gen2.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[1, PMIN] = -sum( bids['P']['qty'][1, :] ) gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([ [-20, -10, 0], [-28, 0, 7] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :10].copy() gencost1[ix_(G, range(NCOST, NCOST + 7))] = array([ [2, 0, 0, 25, 250, 0, 0], [3, -3, -150, 0, 0, 26, 1300], [2, 0, 0, 27, 2700, 0, 0] ]) gencost1[ix_(L, range(NCOST, NCOST + 7))] = c_[array([ [2, -20, -2000, 0, 0], [2, -28, -280, 0, 0] ]), zeros((2, 2))] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers & P bids, lim[\'P\'][\'max_offer\']/[\'min_bid\']' bids['P']['qty'] = array([[20], [28]], float) bids['P']['prc'] = array([[100], [10]], float) lim['P']['min_bid'] = 50.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[G[:2], PMAX] = offers['P']['qty'][:2, :] gen1[r_[G[2], L[1]], GEN_STATUS] = 0 gen1[L[0], [PMIN, QMIN, QMAX]] = array([-20, -10, 0]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0.copy() gencost1[ix_(G[:2], range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300] ]), zeros((2, 4))] gencost1[L[0], NCOST:NCOST + 9] = array([2, -20, -2000, 0, 0, 0, 0, 0, 0]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'P offers & P bids, lim[\'P\'][\'max_offer\']/[\'min_bid\'], multi-block' offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[ 20, 10], [12, 18]], float) bids['P']['prc'] = array([[100, 60], [70, 10]], float) gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[G, PMAX] = array([10, 50, 25]) gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([ [-30, -15, 0], [-12, 0, 3] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :10].copy() gencost1[ix_(G, range(NCOST, NCOST + 7))] = array([ [2, 0, 0, 10, 100, 0, 0], [3, 0, 0, 20, 500, 50, 2450], [2, 0, 0, 25, 1250, 0, 0] ]) gencost1[ix_(L, range(NCOST, NCOST + 7))] = array([ [3, -30, -2600, -20, -2000, 0, 0], [2, -12, -840, 0, 0, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) ##----- reactive ----- ## generator cost data # 1 startup shutdown n x1 y1 ... xn yn # 2 startup shutdown n c(n-1) ... c0 gencost0 = array([ [1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 100, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 0, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 50, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [1, 0, 0, 4, -15, -150, 0, 0, 30, 150, 60, 450], [1, 100, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 3, -20, -15, -10, -10, 0, 0, 0, 0], [1, 0, 0, 3, 0, 0, 40, 80, 60, 180, 0, 0], [1, 0, 50, 2, 0, 0, 0, 0, 0, 0, 0, 0] ], float) t = 'PQ offers only'; offers['P']['qty'] = array([[25], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) offers['Q']['qty'] = array([[10], [20], [30]], float) offers['Q']['prc'] = array([[10], [5], [1]], float) gen, gencost = off2case(gen0, gencost0, offers) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[G, QMAX] = offers['Q']['qty'] gen1[G, QMIN] = 0 gen1[L, GEN_STATUS] = 0 t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0.copy() gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700] ]), zeros((3, 4))] gencost1[ix_(G + nGL - 1, range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 10, 100], [2, 0, 0, 20, 100], [2, 0, 0, 30, 30] ]), zeros((3, 4))] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'PQ offers & PQ bids, lim.P/Q.max_offer/min_bid, multi-block'; offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[ 20, 10], [12, 18]], float) bids['P']['prc'] = array([[100, 60], [70, 10]], float) offers['Q']['qty'] = array([[ 5, 5], [10, 10], [15, 15]], float) offers['Q']['prc'] = array([[10, 20], [ 5, 60], [ 1, 10]], float) bids['Q']['qty'] = array([ 15, 10, 15, 15, 0], float) bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float) lim['Q']['max_offer'] = 50.0 lim['Q']['min_bid'] = -15.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([ [1, 10, 10, -15, 10], [1, 12, 50, -10, 10], [1, -10, 0, -5, 0], [1, 12, 25, 0, 30], [0, -30, 0, 0, 7.5] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST - 1:NCOST + 9] = array([ [2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [3, -30, -2600, -20, -2000, 0, 0, 0, 0], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [2, -15, -75, 0, 0, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'PQ offers & PQ bids, for gen, no P, no shutdown'; gen2 = gen0.copy() gen2[0, PMIN] = 0 offers['P']['qty'] = array([[0, 40], [20, 30], [25, 25]], float) gen, gencost = off2case(gen2, gencost0, offers, bids, lim) gen1[0, [PMIN, PMAX, QMIN, QMAX]] = array([0, 0, -15, 10]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1[0, NCOST:NCOST + 9] = gencost0[0, NCOST:NCOST + 9] t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'PQ offers & PQ bids, for gen, no Q, no shutdown'; offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['Q']['qty'] = array([[ 5, 5], [ 0, 10], [15, 15]], float) bids['Q']['qty'] = array([15, 0, 15, 15, 0], float) gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1[0, [PMIN, PMAX, QMIN, QMAX]] = array([10, 10, -15, 10]) ## restore original gen1[1, [PMIN, PMAX, QMIN, QMAX]] = array([12, 50, 0, 0]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1[ix_([0, 1, 6], range(NCOST, NCOST + 9))] = array([ [2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'PQ offers & PQ bids, lim.P/Q.max_offer/min_bid, multi-block'; offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[10, 0], [12, 18]], float) bids['P']['prc'] = array([[100, 60], [70, 10]], float) offers['Q']['qty'] = array([[5, 5], [10, 10], [15, 15]], float) offers['Q']['prc'] = array([[10, 20], [5, 60], [1, 10]], float) bids['Q']['qty'] = array([15, 10, 10, 15, 0], float) bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float) lim['Q']['max_offer'] = 50.0 lim['Q']['min_bid'] = -15.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([ [1, 10, 10, -15, 10], [1, 12, 50, -10, 10], [1, -10, 0, -5, 0], [1, 12, 25, 0, 30], [0, -30, 0, 0, 7.5] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST:NCOST + 9] = array([ [2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [2, -10, -1000, 0, 0, 0, 0, 0, 0], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [2, -10, -50, 0, 0, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'PQ offers & PQ bids, zero Q load w/P bid, shutdown bugfix'; gen1 = gen0.copy() gen1[4, [QG, QMIN, QMAX]] = 0 gen, gencost = off2case(gen1, gencost0, offers, bids, lim) gen1[:, [PMIN, PMAX, QMIN, QMAX]] = array([ [ 10, 10, -15, 10], [ 12, 50, -10, 10], [-10, 0, -5, 0], [ 12, 25, 0, 30], [-12, 0, 0, 0] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST - 1:NCOST + 9] = array([ [2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [2, -10, -1000, 0, 0, 0, 0, 0, 0], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [2, -12, -840, 0, 0, 0, 0, 0, 0], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [2, -10, -50, 0, 0, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t = 'PQ offers & PQ bids, non-zero Q load w/no P bid, shutdown bugfix'; offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[0, 10], [12, 18]], float) bids['P']['prc'] = array([[100, 40], [70, 10]], float) offers['Q']['qty'] = array([[ 5, 5], [10, 10], [15, 15]], float) offers['Q']['prc'] = array([[10, 20], [ 5, 60], [ 1, 10]], float) bids['Q']['qty'] = array([ 15, 10, 15, 15, 0], float) bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float) lim['Q']['max_offer'] = 50.0 lim['Q']['min_bid'] = -15.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([ [1, 10, 10, -15, 10], [1, 12, 50, -10, 10], [0, -30, 0, -15, 0], [1, 12, 25, 0, 30], [0, -30, 0, 0, 7.5] ]) t_is( gen, gen1, 8, [t, ' - gen'] ) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST - 1:NCOST + 9] = array([ [2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [3, -20, -15, -10, -10, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0] ]) t_is( gencost, gencost1, 8, [t, ' - gencost'] ) t_end()
def scale_load(load, bus, gen=None, load_zone=None, opt=None): """Scales fixed and/or dispatchable loads. Assumes consecutive bus numbering when dealing with dispatchable loads. @param load: Each element specifies the amount of scaling for the corresponding load zone, either as a direct scale factor or as a target quantity. If there are C{nz} load zones this vector has C{nz} elements. @param bus: Standard C{bus} matrix with C{nb} rows, where the fixed active and reactive loads available for scaling are specified in columns C{PD} and C{QD} @param gen: (optional) standard C{gen} matrix with C{ng} rows, where the dispatchable loads available for scaling are specified by columns C{PG}, C{QG}, C{PMIN}, C{QMIN} and C{QMAX} (in rows for which C{isload(gen)} returns C{true}). If C{gen} is empty, it assumes there are no dispatchable loads. @param load_zone: (optional) C{nb} element vector where the value of each element is either zero or the index of the load zone to which the corresponding bus belongs. If C{load_zone[b] = k} then the loads at bus C{b} will be scaled according to the value of C{load[k]}. If C{load_zone[b] = 0}, the loads at bus C{b} will not be modified. If C{load_zone} is empty, the default is determined by the dimensions of the C{load} vector. If C{load} is a scalar, a single system-wide zone including all buses is used, i.e. C{load_zone = ones(nb)}. If C{load} is a vector, the default C{load_zone} is defined as the areas specified in the C{bus} matrix, i.e. C{load_zone = bus[:, BUS_AREA]}, and C{load} should have dimension C{= max(bus[:, BUS_AREA])}. @param opt: (optional) dict with three possible fields, 'scale', 'pq' and 'which' that determine the behavior as follows: - C{scale} (default is 'FACTOR') - 'FACTOR' : C{load} consists of direct scale factors, where C{load[k] =} scale factor C{R[k]} for zone C{k} - 'QUANTITY' : C{load} consists of target quantities, where C{load[k] =} desired total active load in MW for zone C{k} after scaling by an appropriate C{R(k)} - C{pq} (default is 'PQ') - 'PQ' : scale both active and reactive loads - 'P' : scale only active loads - C{which} (default is 'BOTH' if GEN is provided, else 'FIXED') - 'FIXED' : scale only fixed loads - 'DISPATCHABLE' : scale only dispatchable loads - 'BOTH' : scale both fixed and dispatchable loads @see: L{total_load} @author: Ray Zimmerman (PSERC Cornell) """ nb = bus.shape[0] ## number of buses ##----- process inputs ----- bus = bus.copy() if gen is None: gen = array([]) else: gen = gen.copy() if load_zone is None: load_zone = array([], int) if opt is None: opt = {} ## fill out and check opt if len(gen) == 0: opt["which"] = 'FIXED' if 'pq' not in opt: opt["pq"] = 'PQ' ## 'PQ' or 'P' if 'which' not in opt: opt["which"] = 'BOTH' ## 'FIXED', 'DISPATCHABLE' or 'BOTH' if 'scale' not in opt: opt["scale"] = 'FACTOR' ## 'FACTOR' or 'QUANTITY' if (opt["pq"] != 'P') and (opt["pq"] != 'PQ'): stderr.write("scale_load: opt['pq'] must equal 'PQ' or 'P'\n") if (opt["which"][0] != 'F') and (opt["which"][0] != 'D') and (opt["which"][0] != 'B'): stderr.write("scale_load: opt.which should be 'FIXED, 'DISPATCHABLE or 'BOTH'\n") if (opt["scale"][0] != 'F') and (opt["scale"][0] != 'Q'): stderr.write("scale_load: opt.scale should be 'FACTOR or 'QUANTITY'\n") if (len(gen) == 0) and (opt["which"][0] != 'F'): stderr.write('scale_load: need gen matrix to scale dispatchable loads\n') ## create dispatchable load connection matrix if len(gen) > 0: ng = gen.shape[0] is_ld = isload(gen) & (gen[:, GEN_STATUS] > 0) ld = find(is_ld) ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1, int) e2i[i2e] = arange(nb) gbus = gen[:, GEN_BUS].astype(int) Cld = sparse((is_ld, (e2i[gbus], arange(ng))), (nb, ng)) else: ng = 0 ld = array([], int) if len(load_zone) == 0: if len(load) == 1: ## make a single zone of all load buses load_zone = zeros(nb, int) ## initialize load_zone[bus[:, PD] != 0 or bus[:, QD] != 0] = 1 ## FIXED loads if len(gen) > 0: gbus = gen[ld, GEN_BUS].astype(int) load_zone[e2i[gbus]] = 1 ## DISPATCHABLE loads else: ## use areas defined in bus data as zones load_zone = bus[:, BUS_AREA] ## check load_zone to make sure it's consistent with size of load vector if max(load_zone) > len(load): stderr.write('scale_load: load vector must have a value for each load zone specified\n') ##----- compute scale factors for each zone ----- scale = load.copy() Pdd = zeros(nb) ## dispatchable P at each bus if opt["scale"][0] == 'Q': ## 'QUANTITY' ## find load capacity from dispatchable loads if len(gen) > 0: Pdd = -Cld * gen[:, PMIN] ## compute scale factors for k in range(len(load)): idx = find(load_zone == k + 1) fixed = sum(bus[idx, PD]) dispatchable = sum(Pdd[idx]) total = fixed + dispatchable if opt["which"][0] == 'B': ## 'BOTH' if total != 0: scale[k] = load[k] / total elif load[k] == total: scale[k] = 1 else: raise ScalingError('scale_load: impossible to make zone %d load equal %g by scaling non-existent loads\n' % (k, load[k])) elif opt["which"][0] == 'F': ## 'FIXED' if fixed != 0: scale[k] = (load[k] - dispatchable) / fixed elif load[k] == dispatchable: scale[k] = 1 else: raise ScalingError('scale_load: impossible to make zone %d load equal %g by scaling non-existent fixed load\n' % (k, load[k])) elif opt["which"][0] == 'D': ## 'DISPATCHABLE' if dispatchable != 0: scale[k] = (load[k] - fixed) / dispatchable elif load[k] == fixed: scale[k] = 1 else: raise ScalingError('scale_load: impossible to make zone %d load equal %g by scaling non-existent dispatchable load\n' % (k, load[k])) ##----- do the scaling ----- ## fixed loads if opt["which"][0] != 'D': ## includes 'FIXED', not 'DISPATCHABLE' only for k in range(len(scale)): idx = find(load_zone == k + 1) bus[idx, PD] = bus[idx, PD] * scale[k] if opt["pq"] == 'PQ': bus[idx, QD] = bus[idx, QD] * scale[k] ## dispatchable loads if opt["which"][0] != 'F': ## includes 'DISPATCHABLE', not 'FIXED' only for k in range(len(scale)): idx = find(load_zone == k + 1) gbus = gen[ld, GEN_BUS].astype(int) i = find( in1d(e2i[gbus], idx) ) ig = ld[i] gen[ix_(ig, [PG, PMIN])] = gen[ix_(ig, [PG, PMIN])] * scale[k] if opt["pq"] == 'PQ': gen[ix_(ig, [QG, QMIN, QMAX])] = gen[ix_(ig, [QG, QMIN, QMAX])] * scale[k] return bus, gen
def scale_load(load, bus, gen=None, load_zone=None, opt=None): """Scales fixed and/or dispatchable loads. Assumes consecutive bus numbering when dealing with dispatchable loads. @param load: Each element specifies the amount of scaling for the corresponding load zone, either as a direct scale factor or as a target quantity. If there are C{nz} load zones this vector has C{nz} elements. @param bus: Standard C{bus} matrix with C{nb} rows, where the fixed active and reactive loads available for scaling are specified in columns C{PD} and C{QD} @param gen: (optional) standard C{gen} matrix with C{ng} rows, where the dispatchable loads available for scaling are specified by columns C{PG}, C{QG}, C{PMIN}, C{QMIN} and C{QMAX} (in rows for which C{isload(gen)} returns C{true}). If C{gen} is empty, it assumes there are no dispatchable loads. @param load_zone: (optional) C{nb} element vector where the value of each element is either zero or the index of the load zone to which the corresponding bus belongs. If C{load_zone[b] = k} then the loads at bus C{b} will be scaled according to the value of C{load[k]}. If C{load_zone[b] = 0}, the loads at bus C{b} will not be modified. If C{load_zone} is empty, the default is determined by the dimensions of the C{load} vector. If C{load} is a scalar, a single system-wide zone including all buses is used, i.e. C{load_zone = ones(nb)}. If C{load} is a vector, the default C{load_zone} is defined as the areas specified in the C{bus} matrix, i.e. C{load_zone = bus[:, BUS_AREA]}, and C{load} should have dimension C{= max(bus[:, BUS_AREA])}. @param opt: (optional) dict with three possible fields, 'scale', 'pq' and 'which' that determine the behavior as follows: - C{scale} (default is 'FACTOR') - 'FACTOR' : C{load} consists of direct scale factors, where C{load[k] =} scale factor C{R[k]} for zone C{k} - 'QUANTITY' : C{load} consists of target quantities, where C{load[k] =} desired total active load in MW for zone C{k} after scaling by an appropriate C{R(k)} - C{pq} (default is 'PQ') - 'PQ' : scale both active and reactive loads - 'P' : scale only active loads - C{which} (default is 'BOTH' if GEN is provided, else 'FIXED') - 'FIXED' : scale only fixed loads - 'DISPATCHABLE' : scale only dispatchable loads - 'BOTH' : scale both fixed and dispatchable loads @see: L{total_load} @author: Ray Zimmerman (PSERC Cornell) """ nb = bus.shape[0] ## number of buses ##----- process inputs ----- bus = bus.copy() if gen is None: gen = array([]) else: gen = gen.copy() if load_zone is None: load_zone = array([], int) if opt is None: opt = {} ## fill out and check opt if len(gen) == 0: opt["which"] = 'FIXED' if 'pq' not in opt: opt["pq"] = 'PQ' ## 'PQ' or 'P' if 'which' not in opt: opt["which"] = 'BOTH' ## 'FIXED', 'DISPATCHABLE' or 'BOTH' if 'scale' not in opt: opt["scale"] = 'FACTOR' ## 'FACTOR' or 'QUANTITY' if (opt["pq"] != 'P') and (opt["pq"] != 'PQ'): stderr.write("scale_load: opt['pq'] must equal 'PQ' or 'P'\n") if (opt["which"][0] != 'F') and (opt["which"][0] != 'D') and (opt["which"][0] != 'B'): stderr.write( "scale_load: opt.which should be 'FIXED, 'DISPATCHABLE or 'BOTH'\n" ) if (opt["scale"][0] != 'F') and (opt["scale"][0] != 'Q'): stderr.write("scale_load: opt.scale should be 'FACTOR or 'QUANTITY'\n") if (len(gen) == 0) and (opt["which"][0] != 'F'): stderr.write( 'scale_load: need gen matrix to scale dispatchable loads\n') ## create dispatchable load connection matrix if len(gen) > 0: ng = gen.shape[0] is_ld = isload(gen) & (gen[:, GEN_STATUS] > 0) ld = find(is_ld) ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1, int) e2i[i2e] = arange(nb) gbus = gen[:, GEN_BUS].astype(int) Cld = sparse((is_ld, (e2i[gbus], arange(ng))), (nb, ng)) else: ng = 0 ld = array([], int) if len(load_zone) == 0: if len(load) == 1: ## make a single zone of all load buses load_zone = zeros(nb, int) ## initialize load_zone[bus[:, PD] != 0 or bus[:, QD] != 0] = 1 ## FIXED loads if len(gen) > 0: gbus = gen[ld, GEN_BUS].astype(int) load_zone[e2i[gbus]] = 1 ## DISPATCHABLE loads else: ## use areas defined in bus data as zones load_zone = bus[:, BUS_AREA] ## check load_zone to make sure it's consistent with size of load vector if max(load_zone) > len(load): stderr.write( 'scale_load: load vector must have a value for each load zone specified\n' ) ##----- compute scale factors for each zone ----- scale = load.copy() Pdd = zeros(nb) ## dispatchable P at each bus if opt["scale"][0] == 'Q': ## 'QUANTITY' ## find load capacity from dispatchable loads if len(gen) > 0: Pdd = -Cld * gen[:, PMIN] ## compute scale factors for k in range(len(load)): idx = find(load_zone == k + 1) fixed = sum(bus[idx, PD]) dispatchable = sum(Pdd[idx]) total = fixed + dispatchable if opt["which"][0] == 'B': ## 'BOTH' if total != 0: scale[k] = load[k] / total elif load[k] == total: scale[k] = 1 else: raise ScalingError( 'scale_load: impossible to make zone %d load equal %g by scaling non-existent loads\n' % (k, load[k])) elif opt["which"][0] == 'F': ## 'FIXED' if fixed != 0: scale[k] = (load[k] - dispatchable) / fixed elif load[k] == dispatchable: scale[k] = 1 else: raise ScalingError( 'scale_load: impossible to make zone %d load equal %g by scaling non-existent fixed load\n' % (k, load[k])) elif opt["which"][0] == 'D': ## 'DISPATCHABLE' if dispatchable != 0: scale[k] = (load[k] - fixed) / dispatchable elif load[k] == fixed: scale[k] = 1 else: raise ScalingError( 'scale_load: impossible to make zone %d load equal %g by scaling non-existent dispatchable load\n' % (k, load[k])) ##----- do the scaling ----- ## fixed loads if opt["which"][0] != 'D': ## includes 'FIXED', not 'DISPATCHABLE' only for k in range(len(scale)): idx = find(load_zone == k + 1) bus[idx, PD] = bus[idx, PD] * scale[k] if opt["pq"] == 'PQ': bus[idx, QD] = bus[idx, QD] * scale[k] ## dispatchable loads if opt["which"][0] != 'F': ## includes 'DISPATCHABLE', not 'FIXED' only for k in range(len(scale)): idx = find(load_zone == k + 1) gbus = gen[ld, GEN_BUS].astype(int) i = find(in1d(e2i[gbus], idx)) ig = ld[i] gen[ix_(ig, [PG, PMIN])] = gen[ix_(ig, [PG, PMIN])] * scale[k] if opt["pq"] == 'PQ': gen[ix_(ig, [QG, QMIN, QMAX ])] = gen[ix_(ig, [QG, QMIN, QMAX])] * scale[k] return bus, gen
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 runWorker(ID, s, output): client = EthJsonRpc('10.64.83.200', 39000 + ID) obj = web3.Web3(web3.HTTPProvider('http://10.64.83.200:3900' + str(ID))) print(client.eth_accounts()[0]) #print(client1.eth_accounts()[1]) print("Worker %d initialized successfully!" % (ID, )) all_gas = [] nu = 0 #iteration count itermax = s.admmopt.iterMaxlocal #get maximum iteration flag = False new_gas = 0 start_balance = obj.eth.getBalance( obj.toChecksumAddress(client.eth_accounts()[0])) j = 0 s.admmopt.tau = 1 last_block = obj.eth.blockNumber while (1): trans_by_block = obj.eth.getBlockTransactionCount(last_block - j) if (trans_by_block > 0): #dest = list(s.nbor.keys()) #if(ID==1):getNextValues(ID,s,client,obj,last_block - j, trans_by_block) #s.update_z() #s.choose_max_rho() break j = j + 1 prev_convegenceTable = [] P_history = [] Q_history = [] start_time2 = time() while nu <= itermax and not flag: if s.recvmsg: s.update_z() s.choose_max_rho() #print(ID,"i have rho", s.var["rho"]) start_time = time() result = s.pipslopf_solver() end_time = time() if result['eflag'] and nu % 20 == 0: print('Subproblem %d at iteration %d solved!' % (ID, nu)) # print("Time for solving subproblem %d: %ssecs to %ssecs" % (ID, start_time, end_time)) s.update_x() P_history.append(sum(s.var['Pg'])) Q_history.append(sum(s.var['Qg'])) if s.recvmsg: # not the initialization s.update_y() s.update_rho() prev_convegenceTable = s.gapAll[s.ID - 1] # check convergence #if(nu>10):flag = flag = s.converge() s.recvmsg = {} # clear the received messages #s.send() dest = s.nbor.keys() for k in dest: # prepare the message to be sent to neighbor k #tm.sleep(0.05) msg3 = message() msg3.config(s.ID, k, s.var, s.nbor[k].tlidx['int'], s.gapAll) data2 = json.dumps(msg3.__dict__, cls=MyEncoder) json_data = json.JSONEncoder().encode(data2) json_data = '0x' + json_data.encode("utf-8").hex() sampleDict = obj.txpool.content.pending new_gas = new_gas + 18000000000 * obj.eth.estimateGas({ 'to': obj.toChecksumAddress( '0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c'), 'data': json_data }) client.eth_sendTransaction( from_address=client.eth_accounts()[0], to_address="0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c", gas=0xf4240, gas_price=18000000000, value=1, # 2441406250 data=json_data) txpooljson = obj.txpool.content.pending.__dict__ recvmsg = {} twait = s.admmopt.pollWaitingtime dest = list(s.nbor.keys()) recvFlag = [0] * s.region['nnbor'] arrived = 0 # number of arrived neighbors pollround = 0 while arrived < s.region['nwait'] and pollround < 5: #for i in range(len(dest)): #k = dest[i] #s.recvmsg[k] = recvmsg[k] #recvFlag[i] = 1 for k in txpooljson.keys(): txpooljson2 = txpooljson[k].__dict__ last_nonce = max(txpooljson2, key=int) #print(ID,", last nonce",last_nonce) last_nonce_dict = txpooljson2[last_nonce].__dict__ hexjson = last_nonce_dict['input'][2:] jsonstring = codecs.decode(hexjson, "hex").decode('utf-8') jsonvalues = json.JSONDecoder().decode(jsonstring) values_dict = json.loads(jsonvalues, cls=MyDecoder) temp_msg = message() if (values_dict['fID'] in s.nbor.keys()): for last_nonce in range(int(max(txpooljson2, key=int)), 0, -1): last_nonce_dict = txpooljson2[str(last_nonce)].__dict__ hexjson = last_nonce_dict['input'][2:] jsonstring = codecs.decode(hexjson, "hex").decode('utf-8') jsonvalues = json.JSONDecoder().decode(jsonstring) values_dict = json.loads(jsonvalues, cls=MyDecoder) if (values_dict['tID'] == s.ID): break #print(ID,"last nonce=",last_nonce,"from",values_dict['fID']) temp_msg.fID = values_dict['fID'] temp_msg.tID = values_dict['tID'] temp_msg.fields['AVmd'] = numpy.asarray( values_dict['fields']['AVmd']) temp_msg.fields['AVms'] = numpy.asarray( values_dict['fields']['AVms']) temp_msg.fields['AVad'] = numpy.asarray( values_dict['fields']['AVad']) temp_msg.fields['AVas'] = numpy.asarray( values_dict['fields']['AVas']) temp_msg.fields['ymd'] = numpy.asarray( values_dict['fields']['ymd']) temp_msg.fields['yms'] = numpy.asarray( values_dict['fields']['yms']) temp_msg.fields['yad'] = numpy.asarray( values_dict['fields']['yad']) temp_msg.fields['yas'] = numpy.asarray( values_dict['fields']['yas']) temp_msg.fields['rho'] = values_dict['fields']['rho'] temp_msg.fields['convergeTable'] = values_dict['fields'][ 'convergeTable'] if (temp_msg.tID == s.ID): recvmsg[temp_msg.fID] = temp_msg #recvFlag[i] = 1 arrived = len(recvmsg) pollround += 1 s.recvmsg = copy.deepcopy(recvmsg) all_gas.append(new_gas) nu += 1 # record results print("Worker %d finished!" % (ID, )) for k in dest: starting_point = message2() starting_point.config(s.ID, k, s.var, s.nbor[k].tlidx['int'], s.gapAll) data2 = json.dumps(starting_point.__dict__, cls=MyEncoder) json_data = json.JSONEncoder().encode(data2) json_data = '0x' + json_data.encode("utf-8").hex() sampleDict = obj.txpool.content.pending client.eth_sendTransaction( from_address=client.eth_accounts()[0], to_address="0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c", gas=0xf4240, gas_price=18000000000, value=1, # 2441406250 data=json_data) print(starting_point.__dict__) x, f, info, lmbda, output2 = result["x"], result["f"], result[ "eflag"], result["lmbda"], result["output"] nx = len(x) nb = s.region['nb'] ng = s.region['ng'] iv = s.idx['var'] bus = s.region['bus'] gen = s.region['gen'] branch = s.region['branch'] baseMVA = s.region['baseMVA'] Ybus = s.region['Ybus'] ridx = s.idx['rbus']['int'] # idx ranges iVa = iv['iVa'] iVm = iv['iVm'] iPg = iv['iPg'] iQg = iv['iQg'] # grab Pg and Qg gen[:, PG] = x[iPg] * s.region["baseMVA"] gen[:, QG] = x[iQg] * s.region["baseMVA"] bus[:, PD] = bus[:, PD] * s.region["baseMVA"] bus[:, QD] = bus[:, QD] * s.region["baseMVA"] # reconstruct V Va, Vm = x[iVa], x[iVm] V = Vm * exp(1j * Va) #print(V) nl = shape(branch)[0] ## number of branches bus[:, VA] = Va * 180 / pi bus[:, VM] = Vm if shape(branch)[1] < MU_ANGMAX + 1: branch = c_[branch, zeros((nl, MU_ANGMAX + 1 - shape(branch)[1]))] Ybus2, Yf, Yt = makeYbus(baseMVA, bus, branch) #print(Yf) ## compute branch flows Sf = V[branch[:, F_BUS].astype(int)] * conj( Yf * V) ## cplx pwr at "from" bus, p["u"]. St = V[branch[:, T_BUS].astype(int)] * conj( Yt * V) ## cplx pwr at "to" bus, p["u"]. branch[:, PF] = Sf.real * baseMVA branch[:, QF] = Sf.imag * baseMVA branch[:, PT] = St.real * baseMVA branch[:, QT] = St.imag * baseMVA #gen[:, VG] = Vm[ gen[:, GEN_BUS].astype(int) ] nlam = len(lmbda["eqnonlin"]) // 2 lamP = zeros(nb) #for non-included pf balances use 0 as multiplier lamQ = zeros(nb) lamP[s.idx['rbus']['int']] = lmbda["eqnonlin"][:nlam] / s.region["baseMVA"] lamQ[s.idx['rbus']['int']] = lmbda["eqnonlin"][nlam:nlam + nlam] / s.region["baseMVA"] ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen)) objValue1 = 0 objValue2 = 0 fd = stdout fd.write('\n REGION %d' % (s.ID)) fd.write( '\nBus/Area Voltage Generation Load ') fd.write(' Lambda($/MVA-hr)') fd.write( '\n # Mag(pu) Ang(deg) P (MW) Q (MVAr) P (MW) Q (MVAr)') fd.write(' P Q ') fd.write( '\n----- ------- -------- -------- -------- -------- --------') fd.write(' ------- -------') for i in range(nb): for glob, loc in s.idx["mapping"].items(): if loc == i: busid = glob + 1 #bus[i,BUS_I]=glob+1 pass fd.write('\n%5d/' % busid) fd.write('%d%7.3f%9.3f' % tuple(bus[i, [BUS_AREA, VM, VA]])) if bus[i, BUS_TYPE] == REF: fd.write('*') else: fd.write(' ') g = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & ~isload(gen)) ld = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & isload(gen)) if any(g + 1): fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG]))) objValue1 = objValue1 + (lamP[i]) * (sum(gen[g, PG])) else: fd.write(' - - ') if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1): if any(ld + 1): fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]), bus[i, QD] - sum(gen[ld, QG]))) objValue2 = objValue2 + (lamP[i]) * (bus[i, PD] - sum(gen[ld, PG])) else: fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]])) else: fd.write(' - - ') fd.write('%9.3f' % lamP[i]) if abs(lamQ[i]) > 1e-4: fd.write('%8.3f' % lamQ[i]) else: fd.write(' -') fd.write( '\n -------- -------- -------- --------') nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0)) onld = find((gen[:, GEN_STATUS] > 0) & isload(gen)) fd.write('\n Total: %9.2f %9.2f %9.2f %9.2f' % (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) - sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG]))) fd.write('\n') print("Local iteration of worker %d is %d" % (ID, nu)) # calculate local generation cost gencost = s.region['gencost'] pg = s.var['Pg'] """ objValue21=0 for i in range(ng): if(pg[i]>0): objValue1 = objValue1 - gencost[i,COST+1]* pg[i] print(gencost[i,COST+1]* pg[i]) else: objValue21 = objValue21 + gencost[i,COST+1]* (-pg[i]) print(gencost[i,COST+1]* (-pg[i])) objValue2 = objValue21 - objValue2 objValue = objValue1 + objValue2 """ objValue = dot(gencost[:, COST], pg**2) + dot( gencost[:, COST + 1], pg) + sum(gencost[:, COST + 2]) print(objValue) varDual = { 'ymd': s.var['ymd'], 'yad': s.var['yad'], 'yms': s.var['yms'], 'yas': s.var['yas'] } varPrimal = { 'Vm': s.var['Vm'], 'Va': s.var['Va'], 'Pg': s.var['Pg'], 'Qg': s.var['Qg'] } Result = { 'objValue': objValue, 'varPrimal': varPrimal, 'varDual': varDual, 'localiter': nu, 'primalgap': s.pb['primalgap'], 'dualgap': s.pb['dualgap'] } ng = s.region['ng'] for i in range(ng): for glob, loc in s.idx["mapping"].items(): if gen[i, GEN_BUS] == loc: gen[i, GEN_BUS] = glob + 1 break for i in range(nb): for glob, loc in s.idx["mapping"].items(): if loc == i: bus[i, BUS_I] = glob + 1 nl = s.region['nl'] for i in range(nl): for glob, loc in s.idx["mapping"].items(): #print(glob, loc, branch[i, F_BUS]) if branch[i, F_BUS] == loc: #print(branch[tl1,F_BUS]) branch[i, F_BUS] = glob + 1 break for i in range(nl): for glob, loc in s.idx["mapping"].items(): #print(glob, loc, branch[i, F_BUS]) if branch[i, T_BUS] == loc: #print(branch[tl1,F_BUS]) branch[i, T_BUS] = glob + 1 break success = flag reg_nb = find(bus[:, BUS_AREA] == ID) lamP = lamP[ix_(reg_nb, )] lamP2 = numpy.array(lamP) reg_bus = bus[ix_(reg_nb, )] print(reg_bus[:, BUS_I]) reg_lam = numpy.array((reg_bus[:, BUS_I], lamP)) print(reg_lam) ppc = {} ppc["bus"], ppc["gen"], ppc["branch"] = reg_bus, gen, branch ids1 = reg_bus[:, BUS_I] ids = numpy.array(ids1) #ppc["success"] = success #ppc=ext2int(ppc) P_history = [i * s.region["baseMVA"] for i in P_history] Q_history = [i * s.region["baseMVA"] for i in Q_history] #results = int2ext(ppc) """ fig = plt.figure() curfig = fig.add_subplot(1, 2, 1) curfig.plot(P_history, color = 'red', linewidth = 2.5, label = 'P') curfig = fig.add_subplot(1, 2, 2) curfig.plot(Q_history, color = 'blue', linewidth = 2.5, label = 'Q') curfig.set_yscale('log') curfig.legend(loc='upper right') """ #plt.show() """ print(all_gas) while( obj.txpool.inspect.pending.__dict__): pass end_time2 = time() final_balance = obj.eth.getBalance(obj.toChecksumAddress(client.eth_accounts()[0])) print("sasasa",ID, " ",start_balance - final_balance , "Time ", end_time2 - start_time2) """ output.put((ID - 1, Result, ppc["bus"], ppc["gen"], ppc["branch"], success, lamP2, ids, P_history, Q_history)) """
def myprintpf(baseMVA, bus=None, gen=None, branch=None, f=None, success=None, et=None, fd=None, ppopt=None): """Prints power flow results. Prints power flow and optimal power flow results to C{fd} (a file descriptor which defaults to C{stdout}), with the details of what gets printed controlled by the optional C{ppopt} argument, which is a PYPOWER options vector (see L{ppoption} for details). The data can either be supplied in a single C{results} dict, or in the individual arguments: C{baseMVA}, C{bus}, C{gen}, C{branch}, C{f}, C{success} and C{et}, where C{f} is the OPF objective function value, C{success} is C{True} if the solution converged and C{False} otherwise, and C{et} is the elapsed time for the computation in seconds. If C{f} is given, it is assumed that the output is from an OPF run, otherwise it is assumed to be a simple power flow run. Examples:: ppopt = ppoptions(OUT_GEN=1, OUT_BUS=0, OUT_BRANCH=0) fd = open(fname, 'w+b') results = runopf(ppc) printpf(results) printpf(results, fd) printpf(results, fd, ppopt) printpf(baseMVA, bus, gen, branch, f, success, et) printpf(baseMVA, bus, gen, branch, f, success, et, fd) printpf(baseMVA, bus, gen, branch, f, success, et, fd, ppopt) fd.close() @author: Ray Zimmerman (PSERC Cornell) """ ##----- initialization ----- ## default arguments objValue = 0 if isinstance(baseMVA, dict): have_results_struct = 1 results = baseMVA if gen is None: ppopt = ppoption() ## use default options else: ppopt = gen if (ppopt['OUT_ALL'] == 0): return ## nothin' to see here, bail out now if bus is None: fd = stdout ## print to stdout by default else: fd = bus baseMVA, bus, gen, branch, success, et = \ results["baseMVA"], results["bus"], results["gen"], \ results["branch"], results["success"], results["et"] if 'f' in results: f = results["f"] else: f = None else: have_results_struct = 0 if ppopt is None: ppopt = ppoption() ## use default options if fd is None: fd = stdout ## print to stdout by default if ppopt['OUT_ALL'] == 0: return ## nothin' to see here, bail out now isOPF = f is not None ## FALSE -> only simple PF data, TRUE -> OPF data ## options isDC = ppopt['PF_DC'] ## use DC formulation? OUT_ALL = ppopt['OUT_ALL'] OUT_ANY = OUT_ALL == 1 ## set to true if any pretty output is to be generated OUT_SYS_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_SYS_SUM']) OUT_AREA_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_AREA_SUM']) OUT_BUS = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BUS']) OUT_BRANCH = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BRANCH']) OUT_GEN = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_GEN']) OUT_ANY = OUT_ANY | ( (OUT_ALL == -1) and (OUT_SYS_SUM or OUT_AREA_SUM or OUT_BUS or OUT_BRANCH or OUT_GEN)) if OUT_ALL == -1: OUT_ALL_LIM = ppopt['OUT_ALL_LIM'] elif OUT_ALL == 1: OUT_ALL_LIM = 2 else: OUT_ALL_LIM = 0 OUT_ANY = OUT_ANY or (OUT_ALL_LIM >= 1) if OUT_ALL_LIM == -1: OUT_V_LIM = ppopt['OUT_V_LIM'] OUT_LINE_LIM = ppopt['OUT_LINE_LIM'] OUT_PG_LIM = ppopt['OUT_PG_LIM'] OUT_QG_LIM = ppopt['OUT_QG_LIM'] else: OUT_V_LIM = OUT_ALL_LIM OUT_LINE_LIM = OUT_ALL_LIM OUT_PG_LIM = OUT_ALL_LIM OUT_QG_LIM = OUT_ALL_LIM OUT_ANY = OUT_ANY or ( (OUT_ALL_LIM == -1) and (OUT_V_LIM or OUT_LINE_LIM or OUT_PG_LIM or OUT_QG_LIM)) ptol = 1e-4 ## tolerance for displaying shadow prices ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1, int) e2i[i2e] = arange(bus.shape[0]) ## sizes of things nb = bus.shape[0] ## number of buses nl = branch.shape[0] ## number of branches ng = gen.shape[0] ## number of generators ## zero out some data to make printout consistent for DC case if isDC: bus[:, r_[QD, BS]] = zeros((nb, 2)) gen[:, r_[QG, QMAX, QMIN]] = zeros((ng, 3)) branch[:, r_[BR_R, BR_B]] = zeros((nl, 2)) ## parameters ties = find( bus[e2i[branch[:, F_BUS].astype(int)], BUS_AREA] != bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA]) ## area inter-ties tap = ones(nl) ## default tap ratio = 1 for lines xfmr = find(branch[:, TAP]) ## indices of transformers tap[xfmr] = branch[xfmr, TAP] ## include transformer tap ratios tap = tap * exp(1j * pi / 180 * branch[:, SHIFT]) ## add phase shifters nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0)) sorted_areas = sort(bus[:, BUS_AREA]) ## area numbers s_areas = sorted_areas[r_[1, find(diff(sorted_areas)) + 1]] nzsh = find((bus[:, GS] != 0.0) | (bus[:, BS] != 0.0)) allg = find(~isload(gen)) ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen)) onld = find((gen[:, GEN_STATUS] > 0) & isload(gen)) V = bus[:, VM] * exp(-1j * pi / 180 * bus[:, VA]) out = find(branch[:, BR_STATUS] == 0) ## out-of-service branches nout = len(out) if isDC: loss = zeros(nl) else: loss = baseMVA * abs(V[e2i[ branch[:, F_BUS].astype(int) ]] / tap - V[e2i[ branch[:, T_BUS].astype(int) ]])**2 / \ (branch[:, BR_R] - 1j * branch[:, BR_X]) fchg = abs(V[e2i[branch[:, F_BUS].astype(int)]] / tap)**2 * branch[:, BR_B] * baseMVA / 2 tchg = abs( V[e2i[branch[:, T_BUS].astype(int)]])**2 * branch[:, BR_B] * baseMVA / 2 loss[out] = zeros(nout) fchg[out] = zeros(nout) tchg[out] = zeros(nout) ##----- print the stuff ----- if OUT_ANY: ## convergence & elapsed time if success: fd.write('\nConverged in %.2f seconds' % et) else: fd.write('\nDid not converge (%.2f seconds)\n' % et) ## objective function value if isOPF: fd.write('\nObjective Function Value = %.2f $/hr' % f) if OUT_SYS_SUM: fd.write( '\n================================================================================' ) fd.write( '\n| System Summary |' ) fd.write( '\n================================================================================' ) fd.write( '\n\nHow many? How much? P (MW) Q (MVAr)' ) fd.write( '\n--------------------- ------------------- ------------- -----------------' ) fd.write( '\nBuses %6d Total Gen Capacity %7.1f %7.1f to %.1f' % (nb, sum(gen[allg, PMAX]), sum(gen[allg, QMIN]), sum(gen[allg, QMAX]))) fd.write( '\nGenerators %5d On-line Capacity %7.1f %7.1f to %.1f' % (len(allg), sum(gen[ong, PMAX]), sum( gen[ong, QMIN]), sum(gen[ong, QMAX]))) fd.write( '\nCommitted Gens %5d Generation (actual) %7.1f %7.1f' % (len(ong), sum(gen[ong, PG]), sum(gen[ong, QG]))) fd.write( '\nLoads %5d Load %7.1f %7.1f' % (len(nzld) + len(onld), sum(bus[nzld, PD]) - sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG]))) fd.write( '\n Fixed %5d Fixed %7.1f %7.1f' % (len(nzld), sum(bus[nzld, PD]), sum(bus[nzld, QD]))) fd.write( '\n Dispatchable %5d Dispatchable %7.1f of %-7.1f%7.1f' % (len(onld), -sum(gen[onld, PG]), -sum(gen[onld, PMIN]), -sum(gen[onld, QG]))) fd.write( '\nShunts %5d Shunt (inj) %7.1f %7.1f' % (len(nzsh), -sum(bus[nzsh, VM]**2 * bus[nzsh, GS]), sum(bus[nzsh, VM]**2 * bus[nzsh, BS]))) fd.write( '\nBranches %5d Losses (I^2 * Z) %8.2f %8.2f' % (nl, sum(loss.real), sum(loss.imag))) fd.write( '\nTransformers %5d Branch Charging (inj) - %7.1f' % (len(xfmr), sum(fchg) + sum(tchg))) fd.write( '\nInter-ties %5d Total Inter-tie Flow %7.1f %7.1f' % (len(ties), sum(abs(branch[ties, PF] - branch[ties, PT])) / 2, sum(abs(branch[ties, QF] - branch[ties, QT])) / 2)) fd.write('\nAreas %5d' % len(s_areas)) fd.write('\n') fd.write( '\n Minimum Maximum') fd.write( '\n ------------------------- --------------------------------' ) minv = min(bus[:, VM]) mini = argmin(bus[:, VM]) maxv = max(bus[:, VM]) maxi = argmax(bus[:, VM]) fd.write( '\nVoltage Magnitude %7.3f p.u. @ bus %-4d %7.3f p.u. @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) minv = min(bus[:, VA]) mini = argmin(bus[:, VA]) maxv = max(bus[:, VA]) maxi = argmax(bus[:, VA]) fd.write( '\nVoltage Angle %8.2f deg @ bus %-4d %8.2f deg @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) if not isDC: maxv = max(loss.real) maxi = argmax(loss.real) fd.write( '\nP Losses (I^2*R) - %8.2f MW @ line %d-%d' % (maxv, branch[maxi, F_BUS], branch[maxi, T_BUS])) maxv = max(loss.imag) maxi = argmax(loss.imag) fd.write( '\nQ Losses (I^2*X) - %8.2f MVAr @ line %d-%d' % (maxv, branch[maxi, F_BUS], branch[maxi, T_BUS])) if isOPF: minv = min(bus[:, LAM_P]) mini = argmin(bus[:, LAM_P]) maxv = max(bus[:, LAM_P]) maxi = argmax(bus[:, LAM_P]) fd.write( '\nLambda P %8.2f $/MWh @ bus %-4d %8.2f $/MWh @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) minv = min(bus[:, LAM_Q]) mini = argmin(bus[:, LAM_Q]) maxv = max(bus[:, LAM_Q]) maxi = argmax(bus[:, LAM_Q]) fd.write( '\nLambda Q %8.2f $/MWh @ bus %-4d %8.2f $/MWh @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) fd.write('\n') ## bus data if OUT_BUS: fd.write( '\n================================================================================' ) fd.write( '\n| Bus Data |' ) fd.write( '\n================================================================================' ) fd.write( '\n Bus Voltage Generation Load ') if isOPF: fd.write(' Lambda($/MVA-hr)') fd.write( '\n # Mag(pu) Ang(deg) P (MW) Q (MVAr) P (MW) Q (MVAr)') if isOPF: fd.write(' P Q ') fd.write( '\n----- ------- -------- -------- -------- -------- --------') if isOPF: fd.write(' ------- -------') for i in range(nb): fd.write('\n%5d%7.3f%9.3f' % tuple(bus[i, [BUS_I, VM, VA]])) if bus[i, BUS_TYPE] == REF: fd.write('*') else: fd.write(' ') g = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & ~isload(gen)) ld = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & isload(gen)) if any(g + 1): fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG]))) objValue = objValue + bus[i, LAM_P] * (sum(gen[g, PG])) else: fd.write(' - - ') if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1): if any(ld + 1): fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]), bus[i, QD] - sum(gen[ld, QG]))) objValue = objValue + bus[i, LAM_P] * (bus[i, PD] - sum(gen[ld, PG])) else: fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]])) else: fd.write(' - - ') if isOPF: fd.write('%9.3f' % bus[i, LAM_P]) if abs(bus[i, LAM_Q]) > ptol: fd.write('%8.3f' % bus[i, LAM_Q]) else: fd.write(' -') fd.write( '\n -------- -------- -------- --------') fd.write('\n Total: %9.2f %9.2f %9.2f %9.2f' % (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) - sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG]))) fd.write('\n') fd.write('===========ObjValue = %f==============\n' % objValue)
def printpf(baseMVA, bus=None, gen=None, branch=None, f=None, success=None, et=None, fd=None, ppopt=None): """Prints power flow results. Prints power flow and optimal power flow results to C{fd} (a file descriptor which defaults to C{stdout}), with the details of what gets printed controlled by the optional C{ppopt} argument, which is a PYPOWER options vector (see L{ppoption} for details). The data can either be supplied in a single C{results} dict, or in the individual arguments: C{baseMVA}, C{bus}, C{gen}, C{branch}, C{f}, C{success} and C{et}, where C{f} is the OPF objective function value, C{success} is C{True} if the solution converged and C{False} otherwise, and C{et} is the elapsed time for the computation in seconds. If C{f} is given, it is assumed that the output is from an OPF run, otherwise it is assumed to be a simple power flow run. Examples:: ppopt = ppoptions(OUT_GEN=1, OUT_BUS=0, OUT_BRANCH=0) fd = open(fname, 'w+b') results = runopf(ppc) printpf(results) printpf(results, fd) printpf(results, fd, ppopt) printpf(baseMVA, bus, gen, branch, f, success, et) printpf(baseMVA, bus, gen, branch, f, success, et, fd) printpf(baseMVA, bus, gen, branch, f, success, et, fd, ppopt) fd.close() @author: Ray Zimmerman (PSERC Cornell) """ ##----- initialization ----- ## default arguments if isinstance(baseMVA, dict): have_results_struct = 1 results = baseMVA if gen is None: ppopt = ppoption() ## use default options else: ppopt = gen if (ppopt['OUT_ALL'] == 0): return ## nothin' to see here, bail out now if bus is None: fd = stdout ## print to stdout by default else: fd = bus baseMVA, bus, gen, branch, success, et = \ results["baseMVA"], results["bus"], results["gen"], \ results["branch"], results["success"], results["et"] if 'f' in results: f = results["f"] else: f = None else: have_results_struct = 0 if ppopt is None: ppopt = ppoption() ## use default options if fd is None: fd = stdout ## print to stdout by default if ppopt['OUT_ALL'] == 0: return ## nothin' to see here, bail out now isOPF = f is not None ## FALSE -> only simple PF data, TRUE -> OPF data ## options isDC = ppopt['PF_DC'] ## use DC formulation? OUT_ALL = ppopt['OUT_ALL'] OUT_ANY = OUT_ALL == 1 ## set to true if any pretty output is to be generated OUT_SYS_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_SYS_SUM']) OUT_AREA_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_AREA_SUM']) OUT_BUS = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BUS']) OUT_BRANCH = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BRANCH']) OUT_GEN = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_GEN']) OUT_ANY = OUT_ANY | ( (OUT_ALL == -1) and (OUT_SYS_SUM or OUT_AREA_SUM or OUT_BUS or OUT_BRANCH or OUT_GEN)) if OUT_ALL == -1: OUT_ALL_LIM = ppopt['OUT_ALL_LIM'] elif OUT_ALL == 1: OUT_ALL_LIM = 2 else: OUT_ALL_LIM = 0 OUT_ANY = OUT_ANY or (OUT_ALL_LIM >= 1) if OUT_ALL_LIM == -1: OUT_V_LIM = ppopt['OUT_V_LIM'] OUT_LINE_LIM = ppopt['OUT_LINE_LIM'] OUT_PG_LIM = ppopt['OUT_PG_LIM'] OUT_QG_LIM = ppopt['OUT_QG_LIM'] else: OUT_V_LIM = OUT_ALL_LIM OUT_LINE_LIM = OUT_ALL_LIM OUT_PG_LIM = OUT_ALL_LIM OUT_QG_LIM = OUT_ALL_LIM OUT_ANY = OUT_ANY or ( (OUT_ALL_LIM == -1) and (OUT_V_LIM or OUT_LINE_LIM or OUT_PG_LIM or OUT_QG_LIM)) ptol = 1e-4 ## tolerance for displaying shadow prices ## create map of external bus numbers to bus indices i2e = bus[:, BUS_I].astype(int) e2i = zeros(max(i2e) + 1, int) e2i[i2e] = arange(bus.shape[0]) ## sizes of things nb = bus.shape[0] ## number of buses nl = branch.shape[0] ## number of branches ng = gen.shape[0] ## number of generators ## zero out some data to make printout consistent for DC case if isDC: bus[:, r_[QD, BS]] = zeros((nb, 2)) gen[:, r_[QG, QMAX, QMIN]] = zeros((ng, 3)) branch[:, r_[BR_R, BR_B]] = zeros((nl, 2)) ## parameters ties = find( bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] != bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA]) ## area inter-ties tap = ones(nl) ## default tap ratio = 1 for lines xfmr = find(branch[:, TAP]).real ## indices of transformers tap[xfmr] = branch[xfmr, TAP].real ## include transformer tap ratios tap = tap * exp(-1j * pi / 180 * branch[:, SHIFT]) ## add phase shifters nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0)) sorted_areas = sort(bus[:, BUS_AREA]) ## area numbers s_areas = sorted_areas[r_[1, find(diff(sorted_areas)) + 1]] nzsh = find((bus[:, GS] != 0.0) | (bus[:, BS] != 0.0)) allg = find(~isload(gen)) ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen)) onld = find((gen[:, GEN_STATUS] > 0) & isload(gen)) V = bus[:, VM] * exp(-1j * pi / 180 * bus[:, VA]) out = find(branch[:, BR_STATUS] == 0) ## out-of-service branches nout = len(out) if isDC: loss = zeros(nl) else: loss = baseMVA * abs(V[e2i[ branch[:, F_BUS].real.astype(int) ]] / tap - V[e2i[ branch[:, T_BUS].real.astype(int) ]])**2 / \ (branch[:, BR_R] - 1j * branch[:, BR_X]) fchg = abs(V[e2i[branch[:, F_BUS].real.astype(int)]] / tap)**2 * branch[:, BR_B].real * baseMVA / 2 tchg = abs(V[e2i[branch[:, T_BUS].real.astype( int)]])**2 * branch[:, BR_B].real * baseMVA / 2 loss[out] = zeros(nout) fchg[out] = zeros(nout) tchg[out] = zeros(nout) ##----- print the stuff ----- if OUT_ANY: ## convergence & elapsed time if success: fd.write('\nConverged in %.2f seconds' % et) else: fd.write('\nDid not converge (%.2f seconds)\n' % et) ## objective function value if isOPF: fd.write('\nObjective Function Value = %.2f $/hr' % f) if OUT_SYS_SUM: fd.write( '\n================================================================================' ) fd.write( '\n| System Summary |' ) fd.write( '\n================================================================================' ) fd.write( '\n\nHow many? How much? P (MW) Q (MVAr)' ) fd.write( '\n--------------------- ------------------- ------------- -----------------' ) fd.write( '\nBuses %6d Total Gen Capacity %7.1f %7.1f to %.1f' % (nb, sum(gen[allg, PMAX]), sum(gen[allg, QMIN]), sum(gen[allg, QMAX]))) fd.write( '\nGenerators %5d On-line Capacity %7.1f %7.1f to %.1f' % (len(allg), sum(gen[ong, PMAX]), sum( gen[ong, QMIN]), sum(gen[ong, QMAX]))) fd.write( '\nCommitted Gens %5d Generation (actual) %7.1f %7.1f' % (len(ong), sum(gen[ong, PG]), sum(gen[ong, QG]))) fd.write( '\nLoads %5d Load %7.1f %7.1f' % (len(nzld) + len(onld), sum(bus[nzld, PD]) - sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG]))) fd.write( '\n Fixed %5d Fixed %7.1f %7.1f' % (len(nzld), sum(bus[nzld, PD]), sum(bus[nzld, QD]))) fd.write( '\n Dispatchable %5d Dispatchable %7.1f of %-7.1f%7.1f' % (len(onld), -sum(gen[onld, PG]), -sum(gen[onld, PMIN]), -sum(gen[onld, QG]))) fd.write( '\nShunts %5d Shunt (inj) %7.1f %7.1f' % (len(nzsh), -sum(bus[nzsh, VM]**2 * bus[nzsh, GS]), sum(bus[nzsh, VM]**2 * bus[nzsh, BS]))) fd.write( '\nBranches %5d Losses (I^2 * Z) %8.2f %8.2f' % (nl, sum(loss.real), sum(loss.imag))) fd.write( '\nTransformers %5d Branch Charging (inj) - %7.1f' % (len(xfmr), sum(fchg) + sum(tchg))) fd.write( '\nInter-ties %5d Total Inter-tie Flow %7.1f %7.1f' % (len(ties), sum(abs(branch[ties, PF] - branch[ties, PT])) / 2, sum(abs(branch[ties, QF] - branch[ties, QT])) / 2)) fd.write('\nAreas %5d' % len(s_areas)) fd.write('\n') fd.write( '\n Minimum Maximum') fd.write( '\n ------------------------- --------------------------------' ) minv = min(bus[:, VM]) mini = argmin(bus[:, VM]) maxv = max(bus[:, VM]) maxi = argmax(bus[:, VM]) fd.write( '\nVoltage Magnitude %7.3f p.u. @ bus %-4d %7.3f p.u. @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) minv = min(bus[:, VA]) mini = argmin(bus[:, VA]) maxv = max(bus[:, VA]) maxi = argmax(bus[:, VA]) fd.write( '\nVoltage Angle %8.2f deg @ bus %-4d %8.2f deg @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) if not isDC: maxv = max(loss.real) maxi = argmax(loss.real) fd.write( '\nP Losses (I^2*R) - %8.2f MW @ line %d-%d' % (maxv, branch[maxi, F_BUS].real, branch[maxi, T_BUS].real)) maxv = max(loss.imag) maxi = argmax(loss.imag) fd.write( '\nQ Losses (I^2*X) - %8.2f MVAr @ line %d-%d' % (maxv, branch[maxi, F_BUS].real, branch[maxi, T_BUS].real)) if isOPF: minv = min(bus[:, LAM_P]) mini = argmin(bus[:, LAM_P]) maxv = max(bus[:, LAM_P]) maxi = argmax(bus[:, LAM_P]) fd.write( '\nLambda P %8.2f $/MWh @ bus %-4d %8.2f $/MWh @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) minv = min(bus[:, LAM_Q]) mini = argmin(bus[:, LAM_Q]) maxv = max(bus[:, LAM_Q]) maxi = argmax(bus[:, LAM_Q]) fd.write( '\nLambda Q %8.2f $/MWh @ bus %-4d %8.2f $/MWh @ bus %-4d' % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I])) fd.write('\n') if OUT_AREA_SUM: fd.write( '\n================================================================================' ) fd.write( '\n| Area Summary |' ) fd.write( '\n================================================================================' ) fd.write( '\nArea # of # of Gens # of Loads # of # of # of # of' ) fd.write( '\n Num Buses Total Online Total Fixed Disp Shunt Brchs Xfmrs Ties' ) fd.write( '\n---- ----- ----- ------ ----- ----- ----- ----- ----- ----- -----' ) for i in range(len(s_areas)): a = s_areas[i] ib = find(bus[:, BUS_AREA] == a) ig = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & ~isload(gen)) igon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & ~isload(gen)) ildon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & isload(gen)) inzld = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, PD], bus[:, QD])) inzsh = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, GS], bus[:, BS])) ibrch = find( (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a)) in_tie = find( (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] != a)) out_tie = find( (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] != a) & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a)) if not any(xfmr + 1): nxfmr = 0 else: nxfmr = len( find((bus[e2i[branch[xfmr, F_BUS].real.astype(int)], BUS_AREA] == a) & (bus[e2i[branch[xfmr, T_BUS].real.astype(int)], BUS_AREA] == a))) fd.write('\n%3d %6d %5d %5d %5d %5d %5d %5d %5d %5d %5d' % (a, len(ib), len(ig), len(igon), \ len(inzld)+len(ildon), len(inzld), len(ildon), \ len(inzsh), len(ibrch), nxfmr, len(in_tie)+len(out_tie))) fd.write( '\n---- ----- ----- ------ ----- ----- ----- ----- ----- ----- -----' ) fd.write( '\nTot: %6d %5d %5d %5d %5d %5d %5d %5d %5d %5d' % (nb, len(allg), len(ong), len(nzld) + len(onld), len(nzld), len(onld), len(nzsh), nl, len(xfmr), len(ties))) fd.write('\n') fd.write( '\nArea Total Gen Capacity On-line Gen Capacity Generation' ) fd.write( '\n Num MW MVAr MW MVAr MW MVAr' ) fd.write( '\n---- ------ ------------------ ------ ------------------ ------ ------' ) for i in range(len(s_areas)): a = s_areas[i] ig = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & ~isload(gen)) igon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & ~isload(gen)) fd.write( '\n%3d %7.1f %7.1f to %-.1f %7.1f %7.1f to %-7.1f %7.1f %7.1f' % (a, sum(gen[ig, PMAX]), sum(gen[ig, QMIN]), sum( gen[ig, QMAX]), sum(gen[igon, PMAX]), sum(gen[igon, QMIN]), sum(gen[igon, QMAX]), sum(gen[igon, PG]), sum(gen[igon, QG]))) fd.write( '\n---- ------ ------------------ ------ ------------------ ------ ------' ) # fd.write('\nTot: %7.1f %7.1f to %-7.1f %7.1f %7.1f to %-7.1f %7.1f %7.1f' % # (sum(gen[allg, PMAX]), sum(gen[allg, QMIN]), sum(gen[allg, QMAX]), # sum(gen[ong, PMAX]), sum(gen[ong, QMIN]), sum(gen[ong, QMAX]), # sum(gen[ong, PG]), sum(gen[ong, QG]) )) fd.write('\n') fd.write( '\nArea Disp Load Cap Disp Load Fixed Load Total Load' ) fd.write( '\n Num MW MVAr MW MVAr MW MVAr MW MVAr' ) fd.write( '\n---- ------ ------ ------ ------ ------ ------ ------ ------' ) Qlim = (gen[:, QMIN] == 0) * gen[:, QMAX] + (gen[:, QMAX] == 0) * gen[:, QMIN] for i in range(len(s_areas)): a = s_areas[i] ildon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a) & (gen[:, GEN_STATUS] > 0) & isload(gen)) inzld = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, PD], bus[:, QD])) fd.write( '\n%3d %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f' % (a, -sum(gen[ildon, PMIN]), -sum(Qlim[ildon]), -sum(gen[ildon, PG]), -sum(gen[ildon, QG]), sum(bus[inzld, PD]), sum(bus[inzld, QD]), -sum(gen[ildon, PG]) + sum(bus[inzld, PD]), -sum(gen[ildon, QG]) + sum(bus[inzld, QD]))) fd.write( '\n---- ------ ------ ------ ------ ------ ------ ------ ------' ) fd.write( '\nTot: %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f' % (-sum(gen[onld, PMIN]), -sum(Qlim[onld]), -sum(gen[onld, PG]), -sum(gen[onld, QG]), sum(bus[nzld, PD]), sum( bus[nzld, QD]), -sum(gen[onld, PG]) + sum(bus[nzld, PD]), -sum(gen[onld, QG]) + sum(bus[nzld, QD]))) fd.write('\n') fd.write( '\nArea Shunt Inj Branch Series Losses Net Export' ) fd.write( '\n Num MW MVAr Charging MW MVAr MW MVAr' ) fd.write( '\n---- ------ ------ -------- ------ ------ ------ ------' ) for i in range(len(s_areas)): a = s_areas[i] inzsh = find((bus[:, BUS_AREA] == a) & logical_or(bus[:, GS], bus[:, BS])) ibrch = find( (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a) & branch[:, BR_STATUS].astype(bool)) in_tie = find( (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] != a) & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a) & branch[:, BR_STATUS].astype(bool)) out_tie = find( (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a) & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] != a) & branch[:, BR_STATUS].astype(bool)) fd.write( '\n%3d %7.1f %7.1f %7.1f %7.2f %7.2f %7.1f %7.1f' % (a, -sum(bus[inzsh, VM]**2 * bus[inzsh, GS]), sum(bus[inzsh, VM]**2 * bus[inzsh, BS]), sum(fchg[ibrch]) + sum(tchg[ibrch]) + sum(fchg[out_tie]) + sum(tchg[in_tie]), sum(real(loss[ibrch])) + sum(real(loss[r_[in_tie, out_tie]])) / 2, sum(imag(loss[ibrch])) + sum(imag(loss[r_[in_tie, out_tie]])) / 2, sum(branch[in_tie, PT]) + sum(branch[out_tie, PF]) - sum(real(loss[r_[in_tie, out_tie]])) / 2, sum(branch[in_tie, QT]) + sum(branch[out_tie, QF]) - sum(imag(loss[r_[in_tie, out_tie]])) / 2)) fd.write( '\n---- ------ ------ -------- ------ ------ ------ ------' ) fd.write( '\nTot: %7.1f %7.1f %7.1f %7.2f %7.2f - -' % (-sum(bus[nzsh, VM]**2 * bus[nzsh, GS]), sum(bus[nzsh, VM]**2 * bus[nzsh, BS]), sum(fchg) + sum(tchg), sum(real(loss)), sum(imag(loss)))) fd.write('\n') ## generator data if OUT_GEN: if isOPF: genlamP = bus[e2i[gen[:, GEN_BUS].astype(int)], LAM_P] genlamQ = bus[e2i[gen[:, GEN_BUS].astype(int)], LAM_Q] fd.write( '\n================================================================================' ) fd.write( '\n| Generator Data |' ) fd.write( '\n================================================================================' ) fd.write('\n Gen Bus Status Pg Qg ') if isOPF: fd.write(' Lambda ($/MVA-hr)') fd.write('\n # # (MW) (MVAr) ') if isOPF: fd.write(' P Q ') fd.write('\n---- ----- ------ -------- --------') if isOPF: fd.write(' -------- --------') for k in range(len(ong)): i = ong[k] fd.write('\n%3d %6d %2d ' % (i, gen[i, GEN_BUS], gen[i, GEN_STATUS])) if (gen[i, GEN_STATUS] > 0) & logical_or(gen[i, PG], gen[i, QG]): fd.write('%10.2f%10.2f' % (gen[i, PG], gen[i, QG])) else: fd.write(' - - ') if isOPF: fd.write('%10.2f%10.2f' % (genlamP[i], genlamQ[i])) fd.write('\n -------- --------') fd.write('\n Total: %9.2f%10.2f' % (sum(gen[ong, PG]), sum(gen[ong, QG]))) fd.write('\n') if any(onld + 1): fd.write( '\n================================================================================' ) fd.write( '\n| Dispatchable Load Data |' ) fd.write( '\n================================================================================' ) fd.write('\n Gen Bus Status Pd Qd ') if isOPF: fd.write(' Lambda ($/MVA-hr)') fd.write('\n # # (MW) (MVAr) ') if isOPF: fd.write(' P Q ') fd.write('\n---- ----- ------ -------- --------') if isOPF: fd.write(' -------- --------') for k in range(len(onld)): i = onld[k] fd.write('\n%3d %6d %2d ' % (i, gen[i, GEN_BUS], gen[i, GEN_STATUS])) if (gen[i, GEN_STATUS] > 0) & logical_or( gen[i, PG], gen[i, QG]): fd.write('%10.2f%10.2f' % (-gen[i, PG], -gen[i, QG])) else: fd.write(' - - ') if isOPF: fd.write('%10.2f%10.2f' % (genlamP[i], genlamQ[i])) fd.write('\n -------- --------') fd.write('\n Total: %9.2f%10.2f' % (-sum(gen[onld, PG]), -sum(gen[onld, QG]))) fd.write('\n') ## bus data if OUT_BUS: fd.write( '\n================================================================================' ) fd.write( '\n| Bus Data |' ) fd.write( '\n================================================================================' ) fd.write( '\n Bus Voltage Generation Load ') if isOPF: fd.write(' Lambda($/MVA-hr)') fd.write( '\n # Mag(pu) Ang(deg) P (MW) Q (MVAr) P (MW) Q (MVAr)') if isOPF: fd.write(' P Q ') fd.write( '\n----- ------- -------- -------- -------- -------- --------') if isOPF: fd.write(' ------- -------') for i in range(nb): fd.write('\n%5d%7.3f%9.3f' % tuple(bus[i, [BUS_I, VM, VA]])) if bus[i, BUS_TYPE] == REF: fd.write('*') else: fd.write(' ') g = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & ~isload(gen)) ld = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I]) & isload(gen)) if any(g + 1): fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG]))) else: fd.write(' - - ') if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1): if any(ld + 1): fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]), bus[i, QD] - sum(gen[ld, QG]))) else: fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]])) else: fd.write(' - - ') if isOPF: fd.write('%9.3f' % bus[i, LAM_P]) if abs(bus[i, LAM_Q]) > ptol: fd.write('%8.3f' % bus[i, LAM_Q]) else: fd.write(' -') fd.write( '\n -------- -------- -------- --------') fd.write('\n Total: %9.2f %9.2f %9.2f %9.2f' % (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) - sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG]))) fd.write('\n') ## branch data if OUT_BRANCH: fd.write( '\n================================================================================' ) fd.write( '\n| Branch Data |' ) fd.write( '\n================================================================================' ) fd.write( '\nBrnch From To From Bus Injection To Bus Injection Loss (I^2 * Z) ' ) fd.write( '\n # Bus Bus P (MW) Q (MVAr) P (MW) Q (MVAr) P (MW) Q (MVAr)' ) fd.write( '\n----- ----- ----- -------- -------- -------- -------- -------- --------' ) for i in range(nl): fd.write( '\n%4d%7d%7d%10.2f%10.2f%10.2f%10.2f%10.3f%10.2f' % (i, branch[i, F_BUS].real, branch[i, T_BUS].real, branch[i, PF].real, branch[i, QF].real, branch[i, PT].real, branch[i, QT].real, loss[i].real, loss[i].imag)) fd.write( '\n -------- --------' ) fd.write( '\n Total:%10.3f%10.2f' % (sum(real(loss)), sum(imag(loss)))) fd.write('\n') ##----- constraint data ----- if isOPF: ctol = ppopt['OPF_VIOLATION'] ## constraint violation tolerance ## voltage constraints if (not isDC) & ( OUT_V_LIM == 2 | (OUT_V_LIM == 1 & (any(bus[:, VM] < bus[:, VMIN] + ctol) | any(bus[:, VM] > bus[:, VMAX] - ctol) | any(bus[:, MU_VMIN] > ptol) | any(bus[:, MU_VMAX] > ptol)))): fd.write( '\n================================================================================' ) fd.write( '\n| Voltage Constraints |' ) fd.write( '\n================================================================================' ) fd.write('\nBus # Vmin mu Vmin |V| Vmax Vmax mu') fd.write('\n----- -------- ----- ----- ----- --------') for i in range(nb): if (OUT_V_LIM == 2) | (OUT_V_LIM == 1 & ((bus[i, VM] < bus[i, VMIN] + ctol) | (bus[i, VM] > bus[i, VMAX] - ctol) | (bus[i, MU_VMIN] > ptol) | (bus[i, MU_VMAX] > ptol))): fd.write('\n%5d' % bus[i, BUS_I]) if ((bus[i, VM] < bus[i, VMIN] + ctol) | (bus[i, MU_VMIN] > ptol)): fd.write('%10.3f' % bus[i, MU_VMIN]) else: fd.write(' - ') fd.write('%8.3f%7.3f%7.3f' % tuple(bus[i, [VMIN, VM, VMAX]])) if (bus[i, VM] > bus[i, VMAX] - ctol) | (bus[i, MU_VMAX] > ptol): fd.write('%10.3f' % bus[i, MU_VMAX]) else: fd.write(' - ') fd.write('\n') ## generator P constraints if (OUT_PG_LIM == 2) | \ ((OUT_PG_LIM == 1) & (any(gen[ong, PG] < gen[ong, PMIN] + ctol) | any(gen[ong, PG] > gen[ong, PMAX] - ctol) | any(gen[ong, MU_PMIN] > ptol) | any(gen[ong, MU_PMAX] > ptol))) | \ ((not isDC) & ((OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & (any(gen[ong, QG] < gen[ong, QMIN] + ctol) | any(gen[ong, QG] > gen[ong, QMAX] - ctol) | any(gen[ong, MU_QMIN] > ptol) | any(gen[ong, MU_QMAX] > ptol))))): fd.write( '\n================================================================================' ) fd.write( '\n| Generation Constraints |' ) fd.write( '\n================================================================================' ) if (OUT_PG_LIM == 2) | ( (OUT_PG_LIM == 1) & (any(gen[ong, PG] < gen[ong, PMIN] + ctol) | any(gen[ong, PG] > gen[ong, PMAX] - ctol) | any(gen[ong, MU_PMIN] > ptol) | any(gen[ong, MU_PMAX] > ptol))): fd.write('\n Gen Bus Active Power Limits') fd.write( '\n # # Pmin mu Pmin Pg Pmax Pmax mu' ) fd.write( '\n---- ----- ------- -------- -------- -------- -------' ) for k in range(len(ong)): i = ong[k] if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) & ((gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMIN] > ptol) | (gen[i, MU_PMAX] > ptol))): fd.write('\n%4d%6d ' % (i, gen[i, GEN_BUS])) if (gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, MU_PMIN] > ptol): fd.write('%8.3f' % gen[i, MU_PMIN]) else: fd.write(' - ') if gen[i, PG]: fd.write('%10.2f%10.2f%10.2f' % tuple(gen[i, [PMIN, PG, PMAX]])) else: fd.write('%10.2f - %10.2f' % tuple(gen[i, [PMIN, PMAX]])) if (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMAX] > ptol): fd.write('%9.3f' % gen[i, MU_PMAX]) else: fd.write(' - ') fd.write('\n') ## generator Q constraints if (not isDC) & ((OUT_QG_LIM == 2) | ( (OUT_QG_LIM == 1) & (any(gen[ong, QG] < gen[ong, QMIN] + ctol) | any(gen[ong, QG] > gen[ong, QMAX] - ctol) | any(gen[ong, MU_QMIN] > ptol) | any(gen[ong, MU_QMAX] > ptol)))): fd.write('\nGen Bus Reactive Power Limits') fd.write( '\n # # Qmin mu Qmin Qg Qmax Qmax mu') fd.write( '\n--- --- ------- -------- -------- -------- -------') for k in range(len(ong)): i = ong[k] if (OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & ((gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMIN] > ptol) | (gen[i, MU_QMAX] > ptol))): fd.write('\n%3d%5d' % (i, gen[i, GEN_BUS])) if (gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, MU_QMIN] > ptol): fd.write('%8.3f' % gen[i, MU_QMIN]) else: fd.write(' - ') if gen[i, QG]: fd.write('%10.2f%10.2f%10.2f' % tuple(gen[i, [QMIN, QG, QMAX]])) else: fd.write('%10.2f - %10.2f' % tuple(gen[i, [QMIN, QMAX]])) if (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMAX] > ptol): fd.write('%9.3f' % gen[i, MU_QMAX]) else: fd.write(' - ') fd.write('\n') ## dispatchable load P constraints if (OUT_PG_LIM == 2) | (OUT_QG_LIM == 2) | \ ((OUT_PG_LIM == 1) & (any(gen[onld, PG] < gen[onld, PMIN] + ctol) | any(gen[onld, PG] > gen[onld, PMAX] - ctol) | any(gen[onld, MU_PMIN] > ptol) | any(gen[onld, MU_PMAX] > ptol))) | \ ((OUT_QG_LIM == 1) & (any(gen[onld, QG] < gen[onld, QMIN] + ctol) | any(gen[onld, QG] > gen[onld, QMAX] - ctol) | any(gen[onld, MU_QMIN] > ptol) | any(gen[onld, MU_QMAX] > ptol))): fd.write( '\n================================================================================' ) fd.write( '\n| Dispatchable Load Constraints |' ) fd.write( '\n================================================================================' ) if (OUT_PG_LIM == 2) | ( (OUT_PG_LIM == 1) & (any(gen[onld, PG] < gen[onld, PMIN] + ctol) | any(gen[onld, PG] > gen[onld, PMAX] - ctol) | any(gen[onld, MU_PMIN] > ptol) | any(gen[onld, MU_PMAX] > ptol))): fd.write('\nGen Bus Active Power Limits') fd.write( '\n # # Pmin mu Pmin Pg Pmax Pmax mu') fd.write( '\n--- --- ------- -------- -------- -------- -------') for k in range(len(onld)): i = onld[k] if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) & ((gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMIN] > ptol) | (gen[i, MU_PMAX] > ptol))): fd.write('\n%3d%5d' % (i, gen[i, GEN_BUS])) if (gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, MU_PMIN] > ptol): fd.write('%8.3f' % gen[i, MU_PMIN]) else: fd.write(' - ') if gen[i, PG]: fd.write('%10.2f%10.2f%10.2f' % gen[i, [PMIN, PG, PMAX]]) else: fd.write('%10.2f - %10.2f' % gen[i, [PMIN, PMAX]]) if (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMAX] > ptol): fd.write('%9.3f' % gen[i, MU_PMAX]) else: fd.write(' - ') fd.write('\n') ## dispatchable load Q constraints if (not isDC) & ((OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & (any(gen[onld, QG] < gen[onld, QMIN] + ctol) | any(gen[onld, QG] > gen[onld, QMAX] - ctol) | any(gen[onld, MU_QMIN] > ptol) | any(gen[onld, MU_QMAX] > ptol)))): fd.write('\nGen Bus Reactive Power Limits') fd.write( '\n # # Qmin mu Qmin Qg Qmax Qmax mu') fd.write( '\n--- --- ------- -------- -------- -------- -------') for k in range(len(onld)): i = onld[k] if (OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) & ((gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMIN] > ptol) | (gen[i, MU_QMAX] > ptol))): fd.write('\n%3d%5d' % (i, gen(i, GEN_BUS))) if (gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, MU_QMIN] > ptol): fd.write('%8.3f' % gen[i, MU_QMIN]) else: fd.write(' - ') if gen[i, QG]: fd.write('%10.2f%10.2f%10.2f' % gen[i, [QMIN, QG, QMAX]]) else: fd.write('%10.2f - %10.2f' % gen[i, [QMIN, QMAX]]) if (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMAX] > ptol): fd.write('%9.3f' % gen[i, MU_QMAX]) else: fd.write(' - ') fd.write('\n') ## line flow constraints if (ppopt['OPF_FLOW_LIM'] == 1) | isDC: ## P limit Ff = branch[:, PF] Ft = branch[:, PT] strg = '\n # Bus Pf mu Pf |Pmax| Pt Pt mu Bus' elif ppopt['OPF_FLOW_LIM'] == 2: ## |I| limit Ff = abs((branch[:, PF] + 1j * branch[:, QF]) / V[e2i[branch[:, F_BUS].astype(int)]]) Ft = abs((branch[:, PT] + 1j * branch[:, QT]) / V[e2i[branch[:, T_BUS].astype(int)]]) strg = '\n # Bus |If| mu |If| |Imax| |It| |It| mu Bus' else: ## |S| limit Ff = abs(branch[:, PF] + 1j * branch[:, QF]) Ft = abs(branch[:, PT] + 1j * branch[:, QT]) strg = '\n # Bus |Sf| mu |Sf| |Smax| |St| |St| mu Bus' if (OUT_LINE_LIM == 2) | ( (OUT_LINE_LIM == 1) & (any((branch[:, RATE_A] != 0) & (abs(Ff) > branch[:, RATE_A] - ctol)) | any( (branch[:, RATE_A] != 0) & (abs(Ft) > branch[:, RATE_A] - ctol)) | any(branch[:, MU_SF] > ptol) | any(branch[:, MU_ST] > ptol))): fd.write( '\n================================================================================' ) fd.write( '\n| Branch Flow Constraints |' ) fd.write( '\n================================================================================' ) fd.write( '\nBrnch From "From" End Limit "To" End To' ) fd.write(strg) fd.write( '\n----- ----- ------- -------- -------- -------- ------- -----' ) for i in range(nl): if (OUT_LINE_LIM == 2) | ((OUT_LINE_LIM == 1) & ( ((branch[i, RATE_A] != 0) & (abs(Ff[i]) > branch[i, RATE_A] - ctol)) | ((branch[i, RATE_A] != 0) & (abs(Ft[i]) > branch[i, RATE_A] - ctol)) | (branch[i, MU_SF] > ptol) | (branch[i, MU_ST] > ptol))): fd.write('\n%4d%7d' % (i, branch[i, F_BUS])) if (Ff[i] > branch[i, RATE_A] - ctol) | (branch[i, MU_SF] > ptol): fd.write('%10.3f' % branch[i, MU_SF]) else: fd.write(' - ') fd.write('%9.2f%10.2f%10.2f' % (Ff[i], branch[i, RATE_A], Ft[i])) if (Ft[i] > branch[i, RATE_A] - ctol) | (branch[i, MU_ST] > ptol): fd.write('%10.3f' % branch[i, MU_ST]) else: fd.write(' - ') fd.write('%6d' % branch[i, T_BUS]) fd.write('\n') ## execute userfcn callbacks for 'printpf' stage if have_results_struct and 'userfcn' in results: if not isOPF: ## turn off option for all constraints if it isn't an OPF ppopt = ppoption(ppopt, 'OUT_ALL_LIM', 0) run_userfcn(results["userfcn"], 'printpf', results, fd, ppopt)
def userfcn_dcline_ext2int(ppc, args): """This is the 'ext2int' stage userfcn callback that prepares the input data for the formulation stage. It expects to find a 'dcline' field in ppc as described above. The optional args are not currently used. It adds two dummy generators for each in-service DC line, with the appropriate upper and lower generation bounds and corresponding zero-cost entries in gencost. """ c = idx_dcline.c ## initialize some things if 'dclinecost' in ppc: havecost = True else: havecost = False ## save version with external indexing ppc['order']['ext']['dcline'] = ppc['dcline'] ## external indexing if havecost: ppc['order']['ext']['dclinecost'] = ppc['dclinecost'] ## external indexing ## work with only in-service DC lines ppc['order']['dcline']['status']['on'] = find(ppc['dcline'][:, c.BR_STATUS] > 0) ppc['order']['dcline']['status']['off'] = find(ppc['dcline'][:, c.BR_STATUS] <= 0) ## remove out-of-service DC lines dc = ppc['dcline'][ppc['order']['dcline']['status']['on'], :] ## only in-service DC lines if havecost: dcc = ppc['dclinecost'][ppc['order']['dcline']['status']['on'], :] ## only in-service DC lines ppc['dclinecost'] = dcc ndc = dc.shape[0] ## number of in-service DC lines o = ppc['order'] ##----- convert stuff to internal indexing ----- dc[:, c.F_BUS] = o['bus']['e2i'][dc[:, c.F_BUS]] dc[:, c.T_BUS] = o['bus']['e2i'][dc[:, c.T_BUS]] ppc['dcline'] = dc ##----- create gens to represent DC line terminals ----- ## ensure consistency of initial values of PF, PT and losses ## (for simple power flow cases) dc[:, c.PT] = dc[:, c.PF] - (dc[:, c.LOSS0] + dc[:, c.LOSS1] * dc[:, c.PF]) ## create gens fg = zeros(ndc, ppc['gen'].shape[1]) fg[:, MBASE] = 100 fg[:, GEN_STATUS] = dc[:, c.BR_STATUS] ## status (should be all 1's) fg[:, PMIN] = -Inf fg[:, PMAX] = Inf tg = fg fg[:, GEN_BUS] = dc[:, c.F_BUS] ## from bus tg[:, GEN_BUS] = dc[:, c.T_BUS] ## to bus fg[:, PG] = -dc[:, c.PF] ## flow (extracted at "from") tg[:, PG] = dc[:, c.PT] ## flow (injected at "to") fg[:, QG] = dc[:, c.QF] ## VAr injection at "from" tg[:, QG] = dc[:, c.QT] ## VAr injection at "to" fg[:, VG] = dc[:, c.VF] ## voltage set-point at "from" tg[:, VG] = dc[:, c.VT] ## voltage set-point at "to" k = find(dc[:, c.PMIN] >= 0) ## min positive direction flow if len(k) > 0: ## contrain at "from" end fg[k, PMAX] = -dc[k, c.PMIN] ## "from" extraction lower lim k = find(dc[:, c.PMAX] >= 0) ## max positive direction flow if len(k) > 0: ## contrain at "from" end fg[k, PMIN] = -dc[k, c.PMAX] ## "from" extraction upper lim k = find(dc[:, c.PMIN] < 0) ## max negative direction flow if len(k) > 0: ## contrain at "to" end tg[k, PMIN] = dc[k, c.PMIN] ## "to" injection lower lim k = find(dc[:, c.PMAX] < 0) ## min negative direction flow if len(k) > 0: ## contrain at "to" end tg[k, PMAX] = dc[k, c.PMAX] ## "to" injection upper lim fg[:, QMIN] = dc[:, c.QMINF] ## "from" VAr injection lower lim fg[:, QMAX] = dc[:, c.QMAXF] ## "from" VAr injection upper lim tg[:, QMIN] = dc[:, c.QMINT] ## "to" VAr injection lower lim tg[:, QMAX] = dc[:, c.QMAXT] ## "to" VAr injection upper lim ## fudge PMAX a bit if necessary to avoid triggering ## dispatchable load constant power factor constraints fg[isload(fg), PMAX] = -1e-6 tg[isload(tg), PMAX] = -1e-6 ## set all terminal buses to PV (except ref bus) refbus = find(ppc['bus'][:, BUS_TYPE] == REF) ppc['bus'][dc[:, c.F_BUS], BUS_TYPE] = PV ppc['bus'][dc[:, c.T_BUS], BUS_TYPE] = PV ppc['bus'][refbus, BUS_TYPE] = REF ## append dummy gens ppc['gen'] = r_[ppc['gen'], fg, tg] ## gencost if 'gencost' in ppc and len(ppc['gencost']) > 0: ngcr, ngcc = ppc['gencost'].shape ## dimensions of gencost if havecost: ## user has provided costs ndccc = dcc.shape[1] ## number of dclinecost columns ccc = max(r_[ngcc, ndccc]) ## number of columns in new gencost if ccc > ngcc: ## right zero-pad gencost ppc.gencost = c_[ppc['gencost'], zeros(ngcr, ccc-ngcc)] ## flip function across vertical axis and append to gencost ## (PF for DC line = -PG for dummy gen at "from" bus) for k in range(ndc): if dcc[k, MODEL] == POLYNOMIAL: nc = dcc[k, NCOST] temp = dcc[k, NCOST + range(nc + 1)] ## flip sign on coefficients of odd terms ## (every other starting with linear term, ## that is, the next to last one) # temp((nc-1):-2:1) = -temp((nc-1):-2:1) temp[range(nc, 0, -2)] = -temp[range(nc, 0, -2)] else: ## dcc(k, MODEL) == PW_LINEAR nc = dcc[k, NCOST] temp = dcc[k, NCOST + range(2*nc + 1)] ## switch sign on horizontal coordinate xx = -temp[range(0, 2 * nc + 1, 2)] yy = temp[range(1, 2 * nc + 1, 2)] temp[range(0, 2*nc + 1, 2)] = xx[-1::-1] temp[range(1, 2*nc + 1, 2)] = yy[-1::-1] padding = zeros(ccc - NCOST - len(temp)) gck = c_[dcc[k, :NCOST + 1], temp, padding] ## append to gencost ppc['gencost'] = r_[ppc['gencost'], gck] ## use zero cost on "to" end gen tgc = ones((ndc, 1)) * [2, 0, 0, 2, zeros(ccc-4)] ppc['gencost'] = c_[ppc['gencost'], tgc] else: ## use zero cost as default dcgc = ones((2 * ndc, 1)) * [2, 0, 0, 2, zeros(ngcc-4)] ppc.gencost = r_[ppc['gencost'], dcgc] return ppc
def makeAvl(baseMVA, gen): """Construct linear constraints for constant power factor var loads. Constructs parameters for the following linear constraint enforcing a constant power factor constraint for dispatchable loads:: lvl <= Avl * [Pg, Qg] <= uvl C{ivl} is the vector of indices of generators representing variable loads. @author: Ray Zimmerman (PSERC Cornell) @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad Autonoma de Manizales) @author: Richard Lincoln """ ## data dimensions ng = gen.shape[0] ## number of dispatchable injections Pg = gen[:, PG] / baseMVA Qg = gen[:, QG] / baseMVA Pmin = gen[:, PMIN] / baseMVA Qmin = gen[:, QMIN] / baseMVA Qmax = gen[:, QMAX] / baseMVA # Find out if any of these "generators" are actually dispatchable loads. # (see 'help isload' for details on what constitutes a dispatchable load) # Dispatchable loads are modeled as generators with an added constant # power factor constraint. The power factor is derived from the original # value of Pmin and either Qmin (for inductive loads) or Qmax (for # capacitive loads). If both Qmin and Qmax are zero, this implies a unity # power factor without the need for an additional constraint. ivl = find( isload(gen) & ((Qmin != 0) | (Qmax != 0)) ) nvl = ivl.shape[0] ## number of dispatchable loads ## at least one of the Q limits must be zero (corresponding to Pmax == 0) if any( (Qmin[ivl] != 0) & (Qmax[ivl] != 0) ): stderr.write('makeAvl: either Qmin or Qmax must be equal to zero for ' 'each dispatchable load.\n') # Initial values of PG and QG must be consistent with specified power # factor This is to prevent a user from unknowingly using a case file which # would have defined a different power factor constraint under a previous # version which used PG and QG to define the power factor. Qlim = (Qmin[ivl] == 0) * Qmax[ivl] + (Qmax[ivl] == 0) * Qmin[ivl] if any( abs( Qg[ivl] - Pg[ivl] * Qlim / Pmin[ivl] ) > 1e-6 ): stderr.write('makeAvl: For a dispatchable load, PG and QG must be ' 'consistent with the power factor defined by PMIN and ' 'the Q limits.\n') # make Avl, lvl, uvl, for lvl <= Avl * [Pg Qg] <= uvl if nvl > 0: xx = Pmin[ivl] yy = Qlim pftheta = arctan2(yy, xx) pc = sin(pftheta) qc = -cos(pftheta) ii = r_[ arange(nvl), arange(nvl) ] jj = r_[ ivl, ivl + ng ] Avl = sparse((r_[pc, qc], (ii, jj)), (nvl, 2 * ng)) lvl = zeros(nvl) uvl = lvl else: Avl = zeros((0, 2*ng)) lvl = array([]) uvl = array([]) return Avl, lvl, uvl, ivl
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_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
def makeAvl(baseMVA, gen): """Construct linear constraints for constant power factor var loads. Constructs parameters for the following linear constraint enforcing a constant power factor constraint for dispatchable loads:: lvl <= Avl * [Pg, Qg] <= uvl C{ivl} is the vector of indices of generators representing variable loads. @author: Ray Zimmerman (PSERC Cornell) @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad Autonoma de Manizales) """ ## data dimensions ng = gen.shape[0] ## number of dispatchable injections Pg = gen[:, PG] / baseMVA Qg = gen[:, QG] / baseMVA Pmin = gen[:, PMIN] / baseMVA Qmin = gen[:, QMIN] / baseMVA Qmax = gen[:, QMAX] / baseMVA # Find out if any of these "generators" are actually dispatchable loads. # (see 'help isload' for details on what constitutes a dispatchable load) # Dispatchable loads are modeled as generators with an added constant # power factor constraint. The power factor is derived from the original # value of Pmin and either Qmin (for inductive loads) or Qmax (for # capacitive loads). If both Qmin and Qmax are zero, this implies a unity # power factor without the need for an additional constraint. ivl = find(isload(gen) & ((Qmin != 0) | (Qmax != 0))) nvl = ivl.shape[0] ## number of dispatchable loads ## at least one of the Q limits must be zero (corresponding to Pmax == 0) if any((Qmin[ivl] != 0) & (Qmax[ivl] != 0)): stderr.write('makeAvl: either Qmin or Qmax must be equal to zero for ' 'each dispatchable load.\n') # Initial values of PG and QG must be consistent with specified power # factor This is to prevent a user from unknowingly using a case file which # would have defined a different power factor constraint under a previous # version which used PG and QG to define the power factor. Qlim = (Qmin[ivl] == 0) * Qmax[ivl] + (Qmax[ivl] == 0) * Qmin[ivl] if any(abs(Qg[ivl] - Pg[ivl] * Qlim / Pmin[ivl]) > 1e-6): stderr.write('makeAvl: For a dispatchable load, PG and QG must be ' 'consistent with the power factor defined by PMIN and ' 'the Q limits.\n') # make Avl, lvl, uvl, for lvl <= Avl * [Pg Qg] <= uvl if nvl > 0: xx = Pmin[ivl] yy = Qlim pftheta = arctan2(yy, xx) pc = sin(pftheta) qc = -cos(pftheta) ii = r_[arange(nvl), arange(nvl)] jj = r_[ivl, ivl + ng] Avl = sparse((r_[pc, qc], (ii, jj)), (nvl, 2 * ng)) lvl = zeros(nvl) uvl = lvl else: Avl = zeros((0, 2 * ng)) lvl = array([]) uvl = array([]) return Avl, lvl, uvl, ivl
def t_off2case(quiet=False): """Tests for code in C{off2case}. @author: Ray Zimmerman (PSERC Cornell) """ n_tests = 35 t_begin(n_tests, quiet) ## generator data # bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf gen0 = array([[ 1, 10, 0, 60, -15, 1, 100, 1, 60, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 2, 10, 0, 60, -15, 1, 100, 1, 60, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 7, -30, -15, 0, -15, 1, 100, 1, 0, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 13, 10, 0, 60, -15, 1, 100, 1, 60, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 30, -30, 7.5, 7.5, 0, 1, 100, 1, 0, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]], float) ## generator cost data # 1 startup shutdown n x1 y1 ... xn yn # 2 startup shutdown n c(n-1) ... c0 gencost0 = array([[1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 100, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 0, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 50, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000]], float) try: from pypower.extras.smartmarket import off2case except ImportError: t_skip(n_tests, 'smartmarket code not available') return t = 'isload()' t_is(isload(gen0), array([0, 0, 1, 0, 1], bool), 8, t) G = find(~isload(gen0)) L = find(isload(gen0)) nGL = len(G) + len(L) t = 'P offers only' offers = {'P': {}} offers['P']['qty'] = array([[25], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) gen, gencost = off2case(gen0, gencost0, offers) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'].flatten() gen1[L, GEN_STATUS] = 0 t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0.copy() gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([ [2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700], ]), zeros((3, 4))] t_is(gencost, gencost1, 8, [t, ' - gencost']) offers['P']['qty'] = array([[25], [26], [0], [27], [0]], float) offers['P']['prc'] = array([[10], [50], [0], [100], [0]], float) gen, gencost = off2case(gen0, gencost0, offers) t_is(gen, gen1, 8, [t, ' (all rows in offer) - gen']) t_is(gencost, gencost1, 8, [t, ' (all rows in offer) - gencost']) t = 'P offers only (GEN_STATUS=0 for 0 qty offer)' offers['P']['qty'] = array([[0], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) gen, gencost = off2case(gen0, gencost0, offers) gen1 = gen0.copy() gen1[G[1:3], PMAX] = offers['P']['qty'].flatten()[1:3] gen1[G[0], GEN_STATUS] = 0 gen1[L, GEN_STATUS] = 0 t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0.copy() gencost1[ix_(G[1:3], range( NCOST, NCOST + 9))] = c_[array([[2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700]]), zeros((2, 4))] t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers, lim[\'P\'][\'max_offer\']' offers['P']['qty'] = array([[25], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) lim = {'P': {'max_offer': 75}} gen, gencost = off2case(gen0, gencost0, offers, lim=lim) gen1 = gen0.copy() gen1[G[:2], PMAX] = offers['P']['qty'].flatten()[:2, :] gen1[r_[G[2], L], GEN_STATUS] = 0 t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0.copy() gencost1[ix_(G[:2], range( NCOST, NCOST + 9))] = c_[array([[2, 0, 0, 25, 250], [2, 0, 0, 26, 1300]]), zeros((2, 4))] t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers & P bids' bids = { 'P': { 'qty': array([[20], [28]], float), 'prc': array([[100], [10]], float) } } gen, gencost = off2case(gen0, gencost0, offers, bids) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([[-20, -10, 0], [-28, 0, 7]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :8].copy() gencost1[ix_(G, range(NCOST, NCOST + 4))] = array([[2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700]]) gencost1[ix_(L, range(NCOST, NCOST + 4))] = array([[2, -20, -2000, 0, 0], [2, -28, -280, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers & P bids (all rows in bid)' bids['P']['qty'] = array([[0], [0], [20], [0], [28]], float) bids['P']['prc'] = array([[0], [0], [100], [0], [10]], float) gen, gencost = off2case(gen0, gencost0, offers, bids) t_is(gen, gen1, 8, [t, ' - gen']) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers & P bids (GEN_STATUS=0 for 0 qty bid)' bids['P']['qty'] = array([[0], [28]], float) bids['P']['prc'] = array([[100], [10]], float) gen, gencost = off2case(gen0, gencost0, offers, bids) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[L[0], GEN_STATUS] = 0 gen1[L[1], [PMIN, QMIN, QMAX]] = array([-28, 0, 7]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0.copy() gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[ array([[2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700]]), zeros((3, 4))] gencost1[L[1], NCOST:NCOST + 8] = c_[array([[2, -28, -280, 0, 0]]), zeros((1, 4))] t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers & P bids (1 gen with both)' gen2 = gen0.copy() gen2[1, PMIN] = -5 bids['P']['qty'] = array([[0], [3], [20], [0], [28]], float) bids['P']['prc'] = array([[0], [50], [100], [0], [10]], float) gen, gencost = off2case(gen2, gencost0, offers, bids) gen1 = gen2.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[1, PMIN] = -sum(bids['P']['qty'][1, :]) gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([[-20, -10, 0], [-28, 0, 7]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :10].copy() gencost1[ix_(G, range(NCOST, NCOST + 7))] = array([[2, 0, 0, 25, 250, 0, 0], [3, -3, -150, 0, 0, 26, 1300], [2, 0, 0, 27, 2700, 0, 0]]) gencost1[ix_(L, range( NCOST, NCOST + 7))] = c_[array([[2, -20, -2000, 0, 0], [2, -28, -280, 0, 0]]), zeros((2, 2))] t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers & P bids, lim[\'P\'][\'max_offer\']/[\'min_bid\']' bids['P']['qty'] = array([[20], [28]], float) bids['P']['prc'] = array([[100], [10]], float) lim['P']['min_bid'] = 50.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[G[:2], PMAX] = offers['P']['qty'][:2, :] gen1[r_[G[2], L[1]], GEN_STATUS] = 0 gen1[L[0], [PMIN, QMIN, QMAX]] = array([-20, -10, 0]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0.copy() gencost1[ix_(G[:2], range( NCOST, NCOST + 9))] = c_[array([[2, 0, 0, 25, 250], [2, 0, 0, 26, 1300]]), zeros((2, 4))] gencost1[L[0], NCOST:NCOST + 9] = array([2, -20, -2000, 0, 0, 0, 0, 0, 0]) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'P offers & P bids, lim[\'P\'][\'max_offer\']/[\'min_bid\'], multi-block' offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[20, 10], [12, 18]], float) bids['P']['prc'] = array([[100, 60], [70, 10]], float) gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[G, PMAX] = array([10, 50, 25]) gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([[-30, -15, 0], [-12, 0, 3]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :10].copy() gencost1[ix_(G, range(NCOST, NCOST + 7))] = array([[2, 0, 0, 10, 100, 0, 0], [3, 0, 0, 20, 500, 50, 2450], [2, 0, 0, 25, 1250, 0, 0]]) gencost1[ix_(L, range(NCOST, NCOST + 7))] = array([[3, -30, -2600, -20, -2000, 0, 0], [2, -12, -840, 0, 0, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) ##----- reactive ----- ## generator cost data # 1 startup shutdown n x1 y1 ... xn yn # 2 startup shutdown n c(n-1) ... c0 gencost0 = array([[1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 100, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 0, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [1, 0, 0, 4, 0, 0, 12, 240, 36, 1200, 60, 2400], [1, 0, 50, 4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [1, 0, 0, 4, -15, -150, 0, 0, 30, 150, 60, 450], [1, 100, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 3, -20, -15, -10, -10, 0, 0, 0, 0], [1, 0, 0, 3, 0, 0, 40, 80, 60, 180, 0, 0], [1, 0, 50, 2, 0, 0, 0, 0, 0, 0, 0, 0]], float) t = 'PQ offers only' offers['P']['qty'] = array([[25], [26], [27]], float) offers['P']['prc'] = array([[10], [50], [100]], float) offers['Q']['qty'] = array([[10], [20], [30]], float) offers['Q']['prc'] = array([[10], [5], [1]], float) gen, gencost = off2case(gen0, gencost0, offers) gen1 = gen0.copy() gen1[G, PMAX] = offers['P']['qty'] gen1[G, QMAX] = offers['Q']['qty'] gen1[G, QMIN] = 0 gen1[L, GEN_STATUS] = 0 t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0.copy() gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[ array([[2, 0, 0, 25, 250], [2, 0, 0, 26, 1300], [2, 0, 0, 27, 2700]]), zeros((3, 4))] gencost1[ix_(G + nGL - 1, range(NCOST, NCOST + 9))] = c_[ array([[2, 0, 0, 10, 100], [2, 0, 0, 20, 100], [2, 0, 0, 30, 30]]), zeros((3, 4))] t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'PQ offers & PQ bids, lim.P/Q.max_offer/min_bid, multi-block' offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[20, 10], [12, 18]], float) bids['P']['prc'] = array([[100, 60], [70, 10]], float) offers['Q']['qty'] = array([[5, 5], [10, 10], [15, 15]], float) offers['Q']['prc'] = array([[10, 20], [5, 60], [1, 10]], float) bids['Q']['qty'] = array([15, 10, 15, 15, 0], float) bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float) lim['Q']['max_offer'] = 50.0 lim['Q']['min_bid'] = -15.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([[1, 10, 10, -15, 10], [1, 12, 50, -10, 10], [1, -10, 0, -5, 0], [1, 12, 25, 0, 30], [0, -30, 0, 0, 7.5]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST - 1:NCOST + 9] = array( [[2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [3, -30, -2600, -20, -2000, 0, 0, 0, 0], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [2, -15, -75, 0, 0, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'PQ offers & PQ bids, for gen, no P, no shutdown' gen2 = gen0.copy() gen2[0, PMIN] = 0 offers['P']['qty'] = array([[0, 40], [20, 30], [25, 25]], float) gen, gencost = off2case(gen2, gencost0, offers, bids, lim) gen1[0, [PMIN, PMAX, QMIN, QMAX]] = array([0, 0, -15, 10]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1[0, NCOST:NCOST + 9] = gencost0[0, NCOST:NCOST + 9] t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'PQ offers & PQ bids, for gen, no Q, no shutdown' offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['Q']['qty'] = array([[5, 5], [0, 10], [15, 15]], float) bids['Q']['qty'] = array([15, 0, 15, 15, 0], float) gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1[0, [PMIN, PMAX, QMIN, QMAX]] = array([10, 10, -15, 10]) ## restore original gen1[1, [PMIN, PMAX, QMIN, QMAX]] = array([12, 50, 0, 0]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1[ix_([0, 1, 6], range(NCOST, NCOST + 9))] = array( [[2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'PQ offers & PQ bids, lim.P/Q.max_offer/min_bid, multi-block' offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[10, 0], [12, 18]], float) bids['P']['prc'] = array([[100, 60], [70, 10]], float) offers['Q']['qty'] = array([[5, 5], [10, 10], [15, 15]], float) offers['Q']['prc'] = array([[10, 20], [5, 60], [1, 10]], float) bids['Q']['qty'] = array([15, 10, 10, 15, 0], float) bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float) lim['Q']['max_offer'] = 50.0 lim['Q']['min_bid'] = -15.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([[1, 10, 10, -15, 10], [1, 12, 50, -10, 10], [1, -10, 0, -5, 0], [1, 12, 25, 0, 30], [0, -30, 0, 0, 7.5]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST:NCOST + 9] = array( [[2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [2, -10, -1000, 0, 0, 0, 0, 0, 0], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [2, -10, -50, 0, 0, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'PQ offers & PQ bids, zero Q load w/P bid, shutdown bugfix' gen1 = gen0.copy() gen1[4, [QG, QMIN, QMAX]] = 0 gen, gencost = off2case(gen1, gencost0, offers, bids, lim) gen1[:, [PMIN, PMAX, QMIN, QMAX]] = array([[10, 10, -15, 10], [12, 50, -10, 10], [-10, 0, -5, 0], [12, 25, 0, 30], [-12, 0, 0, 0]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST - 1:NCOST + 9] = array([[2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [2, -10, -1000, 0, 0, 0, 0, 0, 0], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [2, -12, -840, 0, 0, 0, 0, 0, 0], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [2, -10, -50, 0, 0, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) t = 'PQ offers & PQ bids, non-zero Q load w/no P bid, shutdown bugfix' offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float) offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float) bids['P']['qty'] = array([[0, 10], [12, 18]], float) bids['P']['prc'] = array([[100, 40], [70, 10]], float) offers['Q']['qty'] = array([[5, 5], [10, 10], [15, 15]], float) offers['Q']['prc'] = array([[10, 20], [5, 60], [1, 10]], float) bids['Q']['qty'] = array([15, 10, 15, 15, 0], float) bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float) lim['Q']['max_offer'] = 50.0 lim['Q']['min_bid'] = -15.0 gen, gencost = off2case(gen0, gencost0, offers, bids, lim) gen1 = gen0.copy() gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([[1, 10, 10, -15, 10], [1, 12, 50, -10, 10], [0, -30, 0, -15, 0], [1, 12, 25, 0, 30], [0, -30, 0, 0, 7.5]]) t_is(gen, gen1, 8, [t, ' - gen']) gencost1 = gencost0[:, :12].copy() gencost1[:, NCOST - 1:NCOST + 9] = array( [[2, 0, 0, 10, 100, 0, 0, 0, 0], [3, 0, 0, 20, 500, 50, 2450, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [2, 0, 0, 25, 1250, 0, 0, 0, 0], [4, -30, 0, -20, 1000, -10, 2000, 0, 3000], [4, -15, 150, 0, 0, 5, 50, 10, 150], [3, -10, 0, 0, 0, 10, 50, 0, 0], [3, -20, -15, -10, -10, 0, 0, 0, 0], [3, 0, 0, 15, 15, 30, 165, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0, 0]]) t_is(gencost, gencost1, 8, [t, ' - gencost']) 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()