Here are the examples of the python api numpy.find taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
46 Examples
0
Example 1
Project: PYPOWER Source File: bustypes.py
def bustypes(bus, gen):
"""Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).
Generators with "out-of-service" status are treated as L{PQ} buses with
zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
and C{gen} have been converted to use internal consecutive bus numbering.
@param bus: bus data
@param gen: generator data
@return: index lists of each bus type
@author: Ray Zimmerman (PSERC Cornell)
"""
# get generator status
nb = bus.shape[0]
ng = gen.shape[0]
# gen connection matrix, element i, j is 1 if, generator j at bus i is ON
Cg = sparse((gen[:, GEN_STATUS] > 0,
(gen[:, GEN_BUS], range(ng))), (nb, ng))
# number of generators at each bus that are ON
bus_gen_status = (Cg * ones(ng, int)).astype(bool)
# form index lists for slack, PV, and PQ buses
ref = find((bus[:, BUS_TYPE] == REF) & bus_gen_status) # ref bus index
pv = find((bus[:, BUS_TYPE] == PV) & bus_gen_status) # PV bus indices
pq = find((bus[:, BUS_TYPE] == PQ) | ~bus_gen_status) # PQ bus indices
# pick a new reference bus if for some reason there is none (may have been
# shut down)
if len(ref) == 0:
ref = pv[0] # use the first PV bus
pv = pv[1:] # take it off PV list
return ref, pv, pq
0
Example 2
Project: PYPOWER Source File: dcopf_solver.py
def dcopf_solver(om, ppopt, out_opt=None):
"""Solves a DC optimal power flow.
Inputs are an OPF model object, a PYPOWER options dict and
a dict containing fields (can be empty) for each of the desired
optional output fields.
Outputs are a C{results} dict, C{success} flag and C{raw} output dict.
C{results} is a PYPOWER case dict (ppc) with the usual baseMVA, bus
branch, gen, gencost fields, along with the following additional
fields:
- C{order} see 'help ext2int' for details of this field
- C{x} final value of optimization variables (internal order)
- C{f} final objective function value
- C{mu} shadow prices on ...
- C{var}
- C{l} lower bounds on variables
- C{u} upper bounds on variables
- C{lin}
- C{l} lower bounds on linear constraints
- C{u} upper bounds on linear constraints
- C{g} (optional) constraint values
- C{dg} (optional) constraint 1st derivatives
- C{df} (optional) obj fun 1st derivatives (not yet implemented)
- C{d2f} (optional) obj fun 2nd derivatives (not yet implemented)
C{success} is C{True} if solver converged successfully, C{False} otherwise.
C{raw} is a raw output dict in form returned by MINOS
- C{xr} final value of optimization variables
- C{pimul} constraint multipliers
- C{info} solver specific termination code
- C{output} solver specific output information
@see: L{opf}, L{qps_pypower}
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
if out_opt is None:
out_opt = {}
## options
verbose = ppopt['VERBOSE']
alg = ppopt['OPF_ALG_DC']
if alg == 0:
if have_fcn('cplex'): ## use CPLEX by default, if available
alg = 500
elif have_fcn('mosek'): ## if not, then MOSEK, if available
alg = 600
elif have_fcn('gurobi'): ## if not, then Gurobi, if available
alg = 700
else: ## otherwise PIPS
alg = 200
## unpack data
ppc = om.get_ppc()
baseMVA, bus, gen, branch, gencost = \
ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
cp = om.get_cost_params()
N, H, Cw = cp["N"], cp["H"], cp["Cw"]
fparm = array(c_[cp["dd"], cp["rh"], cp["kk"], cp["mm"]])
Bf = om.userdata('Bf')
Pfinj = om.userdata('Pfinj')
vv, ll, _, _ = om.get_idx()
## problem dimensions
ipol = find(gencost[:, MODEL] == POLYNOMIAL) ## polynomial costs
ipwl = find(gencost[:, MODEL] == PW_LINEAR) ## piece-wise linear costs
nb = bus.shape[0] ## number of buses
nl = branch.shape[0] ## number of branches
nw = N.shape[0] ## number of general cost vars, w
ny = om.getN('var', 'y') ## number of piece-wise linear costs
nxyz = om.getN('var') ## total number of control vars of all types
## linear constraints & variable bounds
A, l, u = om.linear_constraints()
x0, xmin, xmax = om.getv()
## set up objective function of the form: f = 1/2 * X'*HH*X + CC'*X
## where X = [x;y;z]. First set up as quadratic function of w,
## f = 1/2 * w'*HHw*w + CCw'*w, where w = diag(M) * (N*X - Rhat). We
## will be building on the (optionally present) user supplied parameters.
## piece-wise linear costs
any_pwl = int(ny > 0)
if any_pwl:
# Sum of y vars.
Npwl = sparse((ones(ny), (zeros(ny), arange(vv["i1"]["y"], vv["iN"]["y"]))), (1, nxyz))
Hpwl = sparse((1, 1))
Cpwl = array([1])
fparm_pwl = array([[1, 0, 0, 1]])
else:
Npwl = None#zeros((0, nxyz))
Hpwl = None#array([])
Cpwl = array([])
fparm_pwl = zeros((0, 4))
## quadratic costs
npol = len(ipol)
if any(find(gencost[ipol, NCOST] > 3)):
stderr.write('DC opf cannot handle polynomial costs with higher '
'than quadratic order.\n')
iqdr = find(gencost[ipol, NCOST] == 3)
ilin = find(gencost[ipol, NCOST] == 2)
polycf = zeros((npol, 3)) ## quadratic coeffs for Pg
if len(iqdr) > 0:
polycf[iqdr, :] = gencost[ipol[iqdr], COST:COST + 3]
if npol:
polycf[ilin, 1:3] = gencost[ipol[ilin], COST:COST + 2]
polycf = dot(polycf, diag([ baseMVA**2, baseMVA, 1])) ## convert to p.u.
if npol:
Npol = sparse((ones(npol), (arange(npol), vv["i1"]["Pg"] + ipol)),
(npol, nxyz)) # Pg vars
Hpol = sparse((2 * polycf[:, 0], (arange(npol), arange(npol))),
(npol, npol))
else:
Npol = None
Hpol = None
Cpol = polycf[:, 1]
fparm_pol = ones((npol, 1)) * array([[1, 0, 0, 1]])
## combine with user costs
NN = vstack([n for n in [Npwl, Npol, N] if n is not None and n.shape[0] > 0], "csr")
# FIXME: Zero dimension sparse matrices.
if (Hpwl is not None) and any_pwl and (npol + nw):
Hpwl = hstack([Hpwl, sparse((any_pwl, npol + nw))])
if Hpol is not None:
if any_pwl and npol:
Hpol = hstack([sparse((npol, any_pwl)), Hpol])
if npol and nw:
Hpol = hstack([Hpol, sparse((npol, nw))])
if (H is not None) and nw and (any_pwl + npol):
H = hstack([sparse((nw, any_pwl + npol)), H])
HHw = vstack([h for h in [Hpwl, Hpol, H] if h is not None and h.shape[0] > 0], "csr")
CCw = r_[Cpwl, Cpol, Cw]
ffparm = r_[fparm_pwl, fparm_pol, fparm]
## transform quadratic coefficients for w into coefficients for X
nnw = any_pwl + npol + nw
M = sparse((ffparm[:, 3], (range(nnw), range(nnw))))
MR = M * ffparm[:, 1]
HMR = HHw * MR
MN = M * NN
HH = MN.T * HHw * MN
CC = MN.T * (CCw - HMR)
C0 = 0.5 * dot(MR, HMR) + sum(polycf[:, 2]) # Constant term of cost.
## set up input for QP solver
opt = {'alg': alg, 'verbose': verbose}
if (alg == 200) or (alg == 250):
## try to select an interior initial point
Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180.0)
lb, ub = xmin.copy(), xmax.copy()
lb[xmin == -Inf] = -1e10 ## replace Inf with numerical proxies
ub[xmax == Inf] = 1e10
x0 = (lb + ub) / 2;
# angles set to first reference angle
x0[vv["i1"]["Va"]:vv["iN"]["Va"]] = Varefs[0]
if ny > 0:
ipwl = find(gencost[:, MODEL] == PW_LINEAR)
# largest y-value in CCV data
c = gencost.flatten('F')[sub2ind(gencost.shape, ipwl,
NCOST + 2 * gencost[ipwl, NCOST])]
x0[vv["i1"]["y"]:vv["iN"]["y"]] = max(c) + 0.1 * abs(max(c))
## set up options
feastol = ppopt['PDIPM_FEASTOL']
gradtol = ppopt['PDIPM_GRADTOL']
comptol = ppopt['PDIPM_COMPTOL']
costtol = ppopt['PDIPM_COSTTOL']
max_it = ppopt['PDIPM_MAX_IT']
max_red = ppopt['SCPDIPM_RED_IT']
if feastol == 0:
feastol = ppopt['OPF_VIOLATION'] ## = OPF_VIOLATION by default
opt["pips_opt"] = { 'feastol': feastol,
'gradtol': gradtol,
'comptol': comptol,
'costtol': costtol,
'max_it': max_it,
'max_red': max_red,
'cost_mult': 1 }
elif alg == 400:
opt['ipopt_opt'] = ipopt_options([], ppopt)
elif alg == 500:
opt['cplex_opt'] = cplex_options([], ppopt)
elif alg == 600:
opt['mosek_opt'] = mosek_options([], ppopt)
elif alg == 700:
opt['grb_opt'] = gurobi_options([], ppopt)
else:
raise ValueError("Unrecognised solver [%d]." % alg)
##----- run opf -----
x, f, info, output, lmbda = \
qps_pypower(HH, CC, A, l, u, xmin, xmax, x0, opt)
success = (info == 1)
##----- calculate return values -----
if not any(isnan(x)):
## update solution data
Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]]
f = f + C0
## update voltages & generator outputs
bus[:, VA] = Va * 180 / pi
gen[:, PG] = Pg * baseMVA
## compute branch flows
branch[:, [QF, QT]] = zeros((nl, 2))
branch[:, PF] = (Bf * Va + Pfinj) * baseMVA
branch[:, PT] = -branch[:, PF]
## package up results
mu_l = lmbda["mu_l"]
mu_u = lmbda["mu_u"]
muLB = lmbda["lower"]
muUB = lmbda["upper"]
## update Lagrange multipliers
il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
bus[:, [LAM_P, LAM_Q, MU_VMIN, MU_VMAX]] = zeros((nb, 4))
gen[:, [MU_PMIN, MU_PMAX, MU_QMIN, MU_QMAX]] = zeros((gen.shape[0], 4))
branch[:, [MU_SF, MU_ST]] = zeros((nl, 2))
bus[:, LAM_P] = (mu_u[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]] -
mu_l[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]]) / baseMVA
branch[il, MU_SF] = mu_u[ll["i1"]["Pf"]:ll["iN"]["Pf"]] / baseMVA
branch[il, MU_ST] = mu_u[ll["i1"]["Pt"]:ll["iN"]["Pt"]] / baseMVA
gen[:, MU_PMIN] = muLB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
gen[:, MU_PMAX] = muUB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
pimul = r_[
mu_l - mu_u,
-ones((ny > 0)), ## dummy entry corresponding to linear cost row in A
muLB - muUB
]
mu = { 'var': {'l': muLB, 'u': muUB},
'lin': {'l': mu_l, 'u': mu_u} }
results = deepcopy(ppc)
results["bus"], results["branch"], results["gen"], \
results["om"], results["x"], results["mu"], results["f"] = \
bus, branch, gen, om, x, mu, f
raw = {'xr': x, 'pimul': pimul, 'info': info, 'output': output}
return results, success, raw
0
Example 3
Project: PYPOWER Source File: ext2int.py
def ext2int(ppc, val_or_field=None, ordering=None, dim=0):
"""Converts external to internal indexing.
This function has two forms, the old form that operates on
and returns individual matrices and the new form that operates
on and returns an entire PYPOWER case dict.
1. C{ppc = ext2int(ppc)}
If the input is a single PYPOWER case dict, then all isolated
buses, off-line generators and branches are removed along with any
generators, branches or areas connected to isolated buses. Then the
buses are renumbered consecutively, beginning at 0, and the
generators are sorted by increasing bus number. Any 'ext2int'
callback routines registered in the case are also invoked
automatically. All of the related
indexing information and the original data matrices are stored under
the 'order' key of the dict to be used by C{int2ext} to perform
the reverse conversions. If the case is already using internal
numbering it is returned unchanged.
Example::
ppc = ext2int(ppc)
@see: L{int2ext}, L{e2i_field}, L{e2i_data}
@author: Ray Zimmerman (PSERC Cornell)
"""
ppc = deepcopy(ppc)
if val_or_field is None: # nargin == 1
first = 'order' not in ppc
if first or ppc["order"]["state"] == 'e':
## initialize order
if first:
o = {
'ext': {
'bus': None,
'branch': None,
'gen': None
},
'bus': { 'e2i': None,
'i2e': None,
'status': {} },
'gen': { 'e2i': None,
'i2e': None,
'status': {} },
'branch': { 'status': {} }
}
else:
o = ppc["order"]
## sizes
nb = ppc["bus"].shape[0]
ng = ppc["gen"].shape[0]
ng0 = ng
if 'A' in ppc:
dc = True if ppc["A"].shape[1] < (2 * nb + 2 * ng) else False
elif 'N' in ppc:
dc = True if ppc["N"].shape[1] < (2 * nb + 2 * ng) else False
else:
dc = False
## save data matrices with external ordering
if 'ext' not in o: o['ext'] = {}
o["ext"]["bus"] = ppc["bus"].copy()
o["ext"]["branch"] = ppc["branch"].copy()
o["ext"]["gen"] = ppc["gen"].copy()
if 'areas' in ppc:
if len(ppc["areas"]) == 0: ## if areas field is empty
del ppc['areas'] ## delete it (so it's ignored)
else: ## otherwise
o["ext"]["areas"] = ppc["areas"].copy() ## save it
## check that all buses have a valid BUS_TYPE
bt = ppc["bus"][:, BUS_TYPE]
err = find(~((bt == PQ) | (bt == PV) | (bt == REF) | (bt == NONE)))
if len(err) > 0:
sys.stderr.write('ext2int: bus %d has an invalid BUS_TYPE\n' % err)
## determine which buses, branches, gens are connected and
## in-service
n2i = sparse((range(nb), (ppc["bus"][:, BUS_I], zeros(nb))),
shape=(max(ppc["bus"][:, BUS_I]) + 1, 1))
n2i = array( n2i.todense().flatten() )[0, :] # as 1D array
bs = (bt != NONE) ## bus status
o["bus"]["status"]["on"] = find( bs ) ## connected
o["bus"]["status"]["off"] = find( ~bs ) ## isolated
gs = ( (ppc["gen"][:, GEN_STATUS] > 0) & ## gen status
bs[ n2i[ppc["gen"][:, GEN_BUS].astype(int)] ] )
o["gen"]["status"]["on"] = find( gs ) ## on and connected
o["gen"]["status"]["off"] = find( ~gs ) ## off or isolated
brs = ( ppc["branch"][:, BR_STATUS].astype(int) & ## branch status
bs[n2i[ppc["branch"][:, F_BUS].astype(int)]] &
bs[n2i[ppc["branch"][:, T_BUS].astype(int)]] ).astype(bool)
o["branch"]["status"]["on"] = find( brs ) ## on and conn
o["branch"]["status"]["off"] = find( ~brs )
if 'areas' in ppc:
ar = bs[ n2i[ppc["areas"][:, PRICE_REF_BUS].astype(int)] ]
o["areas"] = {"status": {}}
o["areas"]["status"]["on"] = find( ar )
o["areas"]["status"]["off"] = find( ~ar )
## delete stuff that is "out"
if len(o["bus"]["status"]["off"]) > 0:
# ppc["bus"][o["bus"]["status"]["off"], :] = array([])
ppc["bus"] = ppc["bus"][o["bus"]["status"]["on"], :]
if len(o["branch"]["status"]["off"]) > 0:
# ppc["branch"][o["branch"]["status"]["off"], :] = array([])
ppc["branch"] = ppc["branch"][o["branch"]["status"]["on"], :]
if len(o["gen"]["status"]["off"]) > 0:
# ppc["gen"][o["gen"]["status"]["off"], :] = array([])
ppc["gen"] = ppc["gen"][o["gen"]["status"]["on"], :]
if 'areas' in ppc and (len(o["areas"]["status"]["off"]) > 0):
# ppc["areas"][o["areas"]["status"]["off"], :] = array([])
ppc["areas"] = ppc["areas"][o["areas"]["status"]["on"], :]
## update size
nb = ppc["bus"].shape[0]
## apply consecutive bus numbering
o["bus"]["i2e"] = ppc["bus"][:, BUS_I].copy()
o["bus"]["e2i"] = zeros(max(o["bus"]["i2e"]) + 1)
o["bus"]["e2i"][o["bus"]["i2e"].astype(int)] = arange(nb)
ppc["bus"][:, BUS_I] = \
o["bus"]["e2i"][ ppc["bus"][:, BUS_I].astype(int) ].copy()
ppc["gen"][:, GEN_BUS] = \
o["bus"]["e2i"][ ppc["gen"][:, GEN_BUS].astype(int) ].copy()
ppc["branch"][:, F_BUS] = \
o["bus"]["e2i"][ ppc["branch"][:, F_BUS].astype(int) ].copy()
ppc["branch"][:, T_BUS] = \
o["bus"]["e2i"][ ppc["branch"][:, T_BUS].astype(int) ].copy()
if 'areas' in ppc:
ppc["areas"][:, PRICE_REF_BUS] = \
o["bus"]["e2i"][ ppc["areas"][:,
PRICE_REF_BUS].astype(int) ].copy()
## reorder gens in order of increasing bus number
o["gen"]["e2i"] = argsort(ppc["gen"][:, GEN_BUS])
o["gen"]["i2e"] = argsort(o["gen"]["e2i"])
ppc["gen"] = ppc["gen"][o["gen"]["e2i"].astype(int), :]
if 'int' in o:
del o['int']
o["state"] = 'i'
ppc["order"] = o
## update gencost, A and N
if 'gencost' in ppc:
ordering = ['gen'] ## Pg cost only
if ppc["gencost"].shape[0] == (2 * ng0):
ordering.append('gen') ## include Qg cost
ppc = e2i_field(ppc, 'gencost', ordering)
if 'A' in ppc or 'N' in ppc:
if dc:
ordering = ['bus', 'gen']
else:
ordering = ['bus', 'bus', 'gen', 'gen']
if 'A' in ppc:
ppc = e2i_field(ppc, 'A', ordering, 1)
if 'N' in ppc:
ppc = e2i_field(ppc, 'N', ordering, 1)
## execute userfcn callbacks for 'ext2int' stage
if 'userfcn' in ppc:
ppc = run_userfcn(ppc['userfcn'], 'ext2int', ppc)
else: ## convert extra data
if isinstance(val_or_field, str) or isinstance(val_or_field, list):
## field
warn('Calls of the form ppc = ext2int(ppc, '
'\'field_name\', ...) have been deprecated. Please '
'replace ext2int with e2i_field.', DeprecationWarning)
gen, branch = val_or_field, ordering
ppc = e2i_field(ppc, gen, branch, dim)
else:
## value
warn('Calls of the form val = ext2int(ppc, val, ...) have been '
'deprecated. Please replace ext2int with e2i_data.',
DeprecationWarning)
gen, branch = val_or_field, ordering
ppc = e2i_data(ppc, gen, branch, dim)
return ppc
0
Example 4
Project: PYPOWER Source File: ipoptopf_solver.py
def ipoptopf_solver(om, ppopt):
"""Solves AC optimal power flow using IPOPT.
Inputs are an OPF model object and a PYPOWER options vector.
Outputs are a C{results} dict, C{success} flag and C{raw} output dict.
C{results} is a PYPOWER case dict (ppc) with the usual C{baseMVA}, C{bus}
C{branch}, C{gen}, C{gencost} fields, along with the following additional
fields:
- C{order} see 'help ext2int' for details of this field
- C{x} final value of optimization variables (internal order)
- C{f} final objective function value
- C{mu} shadow prices on ...
- C{var}
- C{l} lower bounds on variables
- C{u} upper bounds on variables
- C{nln}
- C{l} lower bounds on nonlinear constraints
- C{u} upper bounds on nonlinear constraints
- C{lin}
- C{l} lower bounds on linear constraints
- C{u} upper bounds on linear constraints
C{success} is C{True} if solver converged successfully, C{False} otherwise
C{raw} is a raw output dict in form returned by MINOS
- C{xr} final value of optimization variables
- C{pimul} constraint multipliers
- C{info} solver specific termination code
- C{output} solver specific output information
@see: L{opf}, L{pips}
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
import pyipopt
## unpack data
ppc = om.get_ppc()
baseMVA, bus, gen, branch, gencost = \
ppc['baseMVA'], ppc['bus'], ppc['gen'], ppc['branch'], ppc['gencost']
vv, _, nn, _ = om.get_idx()
## problem dimensions
nb = shape(bus)[0] ## number of buses
ng = shape(gen)[0] ## number of gens
nl = shape(branch)[0] ## number of branches
ny = om.getN('var', 'y') ## number of piece-wise linear costs
## linear constraints
A, l, u = om.linear_constraints()
## bounds on optimization vars
_, xmin, xmax = om.getv()
## build admittance matrices
Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)
## try to select an interior initial point
ll = xmin.copy(); uu = xmax.copy()
ll[xmin == -Inf] = -2e19 ## replace Inf with numerical proxies
uu[xmax == Inf] = 2e19
x0 = (ll + uu) / 2
Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180)
x0[vv['i1']['Va']:vv['iN']['Va']] = Varefs[0] ## angles set to first reference angle
if ny > 0:
ipwl = find(gencost[:, MODEL] == PW_LINEAR)
# PQ = r_[gen[:, PMAX], gen[:, QMAX]]
# c = totcost(gencost[ipwl, :], PQ[ipwl])
## largest y-value in CCV data
c = gencost.flatten('F')[sub2ind(shape(gencost), ipwl, NCOST + 2 * gencost[ipwl, NCOST])]
x0[vv['i1']['y']:vv['iN']['y']] = max(c) + 0.1 * abs(max(c))
# x0[vv['i1']['y']:vv['iN']['y']) = c + 0.1 * abs(c)
## find branches with flow limits
il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
nl2 = len(il) ## number of constrained lines
##----- run opf -----
## build Jacobian and Hessian structure
if A is not None and issparse(A):
nA = A.shape[0] ## number of original linear constraints
else:
nA = 0
nx = len(x0)
f = branch[:, F_BUS] ## list of "from" buses
t = branch[:, T_BUS] ## list of "to" buses
Cf = sparse((ones(nl), (arange(nl), f)), (nl, nb)) ## connection matrix for line & from buses
Ct = sparse((ones(nl), (arange(nl), t)), (nl, nb)) ## connection matrix for line & to buses
Cl = Cf + Ct
Cb = Cl.T * Cl + speye(nb, nb)
Cl2 = Cl[il, :]
Cg = sparse((ones(ng), (gen[:, GEN_BUS], arange(ng))), (nb, ng))
nz = nx - 2 * (nb + ng)
nxtra = nx - 2 * nb
if nz > 0:
Js = vstack([
hstack([Cb, Cb, Cg, sparse((nb, ng)), sparse((nb, nz))]),
hstack([Cb, Cb, sparse((nb, ng)), Cg, sparse((nb, nz))]),
hstack([Cl2, Cl2, sparse((nl2, 2 * ng)), sparse((nl2, nz))]),
hstack([Cl2, Cl2, sparse((nl2, 2 * ng)), sparse((nl2, nz))])
], 'coo')
else:
Js = vstack([
hstack([Cb, Cb, Cg, sparse((nb, ng))]),
hstack([Cb, Cb, sparse((nb, ng)), Cg, ]),
hstack([Cl2, Cl2, sparse((nl2, 2 * ng)), ]),
hstack([Cl2, Cl2, sparse((nl2, 2 * ng)), ])
], 'coo')
if A is not None and issparse(A):
Js = vstack([Js, A], 'coo')
f, _, d2f = opf_costfcn(x0, om, True)
Hs = tril(d2f + vstack([
hstack([Cb, Cb, sparse((nb, nxtra))]),
hstack([Cb, Cb, sparse((nb, nxtra))]),
sparse((nxtra, nx))
]), format='coo')
## set options struct for IPOPT
# options = {}
# options['ipopt'] = ipopt_options([], ppopt)
## extra data to pass to functions
userdata = {
'om': om,
'Ybus': Ybus,
'Yf': Yf[il, :],
'Yt': Yt[il, :],
'ppopt': ppopt,
'il': il,
'A': A,
'nA': nA,
'neqnln': 2 * nb,
'niqnln': 2 * nl2,
'Js': Js,
'Hs': Hs
}
## check Jacobian and Hessian structure
#xr = rand(x0.shape)
#lmbda = rand( 2 * nb + 2 * nl2)
#Js1 = eval_jac_g(x, flag, userdata) #(xr, options.auxdata)
#Hs1 = eval_h(xr, 1, lmbda, userdata)
#i1, j1, s = find(Js)
#i2, j2, s = find(Js1)
#if (len(i1) != len(i2)) | (norm(i1 - i2) != 0) | (norm(j1 - j2) != 0):
# raise ValueError, 'something''s wrong with the Jacobian structure'
#
#i1, j1, s = find(Hs)
#i2, j2, s = find(Hs1)
#if (len(i1) != len(i2)) | (norm(i1 - i2) != 0) | (norm(j1 - j2) != 0):
# raise ValueError, 'something''s wrong with the Hessian structure'
## define variable and constraint bounds
# n is the number of variables
n = x0.shape[0]
# xl is the lower bound of x as bounded constraints
xl = xmin
# xu is the upper bound of x as bounded constraints
xu = xmax
neqnln = 2 * nb
niqnln = 2 * nl2
# number of constraints
m = neqnln + niqnln + nA
# lower bound of constraint
gl = r_[zeros(neqnln), -Inf * ones(niqnln), l]
# upper bound of constraints
gu = r_[zeros(neqnln), zeros(niqnln), u]
# number of nonzeros in Jacobi matrix
nnzj = Js.nnz
# number of non-zeros in Hessian matrix, you can set it to 0
nnzh = Hs.nnz
eval_hessian = True
if eval_hessian:
hessian = lambda x, lagrange, obj_factor, flag, user_data=None: \
eval_h(x, lagrange, obj_factor, flag, userdata)
nlp = pyipopt.create(n, xl, xu, m, gl, gu, nnzj, nnzh,
eval_f, eval_grad_f, eval_g, eval_jac_g, hessian)
else:
nnzh = 0
nlp = pyipopt.create(n, xl, xu, m, gl, gu, nnzj, nnzh,
eval_f, eval_grad_f, eval_g, eval_jac_g)
nlp.int_option('print_level', 5)
nlp.num_option('tol', 1.0000e-12)
nlp.int_option('max_iter', 250)
nlp.num_option('dual_inf_tol', 0.10000)
nlp.num_option('constr_viol_tol', 1.0000e-06)
nlp.num_option('compl_inf_tol', 1.0000e-05)
nlp.num_option('acceptable_tol', 1.0000e-08)
nlp.num_option('acceptable_constr_viol_tol', 1.0000e-04)
nlp.num_option('acceptable_compl_inf_tol', 0.0010000)
nlp.str_option('mu_strategy', 'adaptive')
iter = 0
def intermediate_callback(algmod, iter_count, obj_value, inf_pr, inf_du,
mu, d_norm, regularization_size, alpha_du, alpha_pr, ls_trials,
user_data=None):
iter = iter_count
return True
nlp.set_intermediate_callback(intermediate_callback)
## run the optimization
# returns final solution x, upper and lower bound for multiplier, final
# objective function obj and the return status of ipopt
x, zl, zu, obj, status, zg = nlp.solve(x0, m, userdata)
info = {'x': x, 'zl': zl, 'zu': zu, 'obj': obj, 'status': status, 'lmbda': zg}
nlp.close()
success = (status == 0) | (status == 1)
output = {'iterations': iter}
f, _ = opf_costfcn(x, om)
## update solution data
Va = x[vv['i1']['Va']:vv['iN']['Va']]
Vm = x[vv['i1']['Vm']:vv['iN']['Vm']]
Pg = x[vv['i1']['Pg']:vv['iN']['Pg']]
Qg = x[vv['i1']['Qg']:vv['iN']['Qg']]
V = Vm * exp(1j * Va)
##----- calculate return values -----
## update voltages & generator outputs
bus[:, VA] = Va * 180 / pi
bus[:, VM] = Vm
gen[:, PG] = Pg * baseMVA
gen[:, QG] = Qg * baseMVA
gen[:, VG] = Vm[gen[:, GEN_BUS].astype(int)]
## compute branch flows
f_br = branch[:, F_BUS].astype(int)
t_br = branch[:, T_BUS].astype(int)
Sf = V[f_br] * conj(Yf * V) ## cplx pwr at "from" bus, p.u.
St = V[t_br] * 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
## line constraint is actually on square of limit
## so we must fix multipliers
muSf = zeros(nl)
muSt = zeros(nl)
if len(il) > 0:
muSf[il] = 2 * info['lmbda'][2 * nb + arange(nl2)] * branch[il, RATE_A] / baseMVA
muSt[il] = 2 * info['lmbda'][2 * nb + nl2 + arange(nl2)] * branch[il, RATE_A] / baseMVA
## update Lagrange multipliers
bus[:, MU_VMAX] = info['zu'][vv['i1']['Vm']:vv['iN']['Vm']]
bus[:, MU_VMIN] = info['zl'][vv['i1']['Vm']:vv['iN']['Vm']]
gen[:, MU_PMAX] = info['zu'][vv['i1']['Pg']:vv['iN']['Pg']] / baseMVA
gen[:, MU_PMIN] = info['zl'][vv['i1']['Pg']:vv['iN']['Pg']] / baseMVA
gen[:, MU_QMAX] = info['zu'][vv['i1']['Qg']:vv['iN']['Qg']] / baseMVA
gen[:, MU_QMIN] = info['zl'][vv['i1']['Qg']:vv['iN']['Qg']] / baseMVA
bus[:, LAM_P] = info['lmbda'][nn['i1']['Pmis']:nn['iN']['Pmis']] / baseMVA
bus[:, LAM_Q] = info['lmbda'][nn['i1']['Qmis']:nn['iN']['Qmis']] / baseMVA
branch[:, MU_SF] = muSf / baseMVA
branch[:, MU_ST] = muSt / baseMVA
## package up results
nlnN = om.getN('nln')
## extract multipliers for nonlinear constraints
kl = find(info['lmbda'][:2 * nb] < 0)
ku = find(info['lmbda'][:2 * nb] > 0)
nl_mu_l = zeros(nlnN)
nl_mu_u = r_[zeros(2 * nb), muSf, muSt]
nl_mu_l[kl] = -info['lmbda'][kl]
nl_mu_u[ku] = info['lmbda'][ku]
## extract multipliers for linear constraints
lam_lin = info['lmbda'][2 * nb + 2 * nl2 + arange(nA)] ## lmbda for linear constraints
kl = find(lam_lin < 0) ## lower bound binding
ku = find(lam_lin > 0) ## upper bound binding
mu_l = zeros(nA)
mu_l[kl] = -lam_lin[kl]
mu_u = zeros(nA)
mu_u[ku] = lam_lin[ku]
mu = {
'var': {'l': info['zl'], 'u': info['zu']},
'nln': {'l': nl_mu_l, 'u': nl_mu_u}, \
'lin': {'l': mu_l, 'u': mu_u}
}
results = ppc
results['bus'], results['branch'], results['gen'], \
results['om'], results['x'], results['mu'], results['f'] = \
bus, branch, gen, om, x, mu, f
pimul = r_[
results['mu']['nln']['l'] - results['mu']['nln']['u'],
results['mu']['lin']['l'] - results['mu']['lin']['u'],
-ones(ny > 0),
results['mu']['var']['l'] - results['mu']['var']['u']
]
raw = {'xr': x, 'pimul': pimul, 'info': info['status'], 'output': output}
return results, success, raw
0
Example 5
Project: PYPOWER Source File: makeAang.py
def makeAang(baseMVA, branch, nb, ppopt):
"""Construct constraints for branch angle difference limits.
Constructs the parameters for the following linear constraint limiting
the voltage angle differences across branches, where C{Va} is the vector
of bus voltage angles. C{nb} is the number of buses::
lang <= Aang * Va <= uang
C{iang} is the vector of indices of branches with angle difference limits.
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
## options
ignore_ang_lim = ppopt['OPF_IGNORE_ANG_LIM']
if ignore_ang_lim:
Aang = zeros((0, nb))
lang = array([])
uang = array([])
iang = array([])
else:
iang = find(((branch[:, ANGMIN] != 0) & (branch[:, ANGMIN] > -360)) |
((branch[:, ANGMAX] != 0) & (branch[:, ANGMAX] < 360)))
iangl = find(branch[iang, ANGMIN])
iangh = find(branch[iang, ANGMAX])
nang = len(iang)
if nang > 0:
ii = r_[arange(nang), arange(nang)]
jj = r_[branch[iang, F_BUS], branch[iang, T_BUS]]
Aang = sparse((r_[ones(nang), -ones(nang)],
(ii, jj)), (nang, nb))
uang = Inf * ones(nang)
lang = -uang
lang[iangl] = branch[iang[iangl], ANGMIN] * pi / 180
uang[iangh] = branch[iang[iangh], ANGMAX] * pi / 180
else:
Aang = zeros((0, nb))
lang = array([])
uang = array([])
return Aang, lang, uang, iang
0
Example 6
Project: PYPOWER Source File: makeApq.py
def makeApq(baseMVA, gen):
"""Construct linear constraints for generator capability curves.
Constructs the parameters for the following linear constraints
implementing trapezoidal generator capability curves, where
C{Pg} and C{Qg} are the real and reactive generator injections::
Apqh * [Pg, Qg] <= ubpqh
Apql * [Pg, Qg] <= ubpql
C{data} constains additional information as shown below.
Example::
Apqh, ubpqh, Apql, ubpql, data = makeApq(baseMVA, gen)
data['h'] [Qc1max-Qc2max, Pc2-Pc1]
data['l'] [Qc2min-Qc1min, Pc1-Pc2]
data['ipqh'] indices of gens with general PQ cap curves (upper)
data['ipql'] indices of gens with general PQ cap curves (lower)
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
data = {}
## data dimensions
ng = gen.shape[0] ## number of dispatchable injections
## which generators require additional linear constraints
## (in addition to simple box constraints) on (Pg,Qg) to correctly
## model their PQ capability curves
ipqh = find( hasPQcap(gen, 'U') )
ipql = find( hasPQcap(gen, 'L') )
npqh = ipqh.shape[0] ## number of general PQ capability curves (upper)
npql = ipql.shape[0] ## number of general PQ capability curves (lower)
## make Apqh if there is a need to add general PQ capability curves
## use normalized coefficient rows so multipliers have right scaling
## in $$/pu
if npqh > 0:
data["h"] = c_[gen[ipqh, QC1MAX] - gen[ipqh, QC2MAX],
gen[ipqh, PC2] - gen[ipqh, PC1]]
ubpqh = data["h"][:, 0] * gen[ipqh, PC1] + \
data["h"][:, 1] * gen[ipqh, QC1MAX]
for i in range(npqh):
tmp = linalg.norm(data["h"][i, :])
data["h"][i, :] = data["h"][i, :] / tmp
ubpqh[i] = ubpqh[i] / tmp
Apqh = sparse((data["h"].flatten('F'),
(r_[arange(npqh), arange(npqh)], r_[ipqh, ipqh+ng])),
(npqh, 2*ng))
ubpqh = ubpqh / baseMVA
else:
data["h"] = array([])
Apqh = zeros((0, 2*ng))
ubpqh = array([])
## similarly Apql
if npql > 0:
data["l"] = c_[gen[ipql, QC2MIN] - gen[ipql, QC1MIN],
gen[ipql, PC1] - gen[ipql, PC2]]
ubpql = data["l"][:, 0] * gen[ipql, PC1] + \
data["l"][:, 1] * gen[ipql, QC1MIN]
for i in range(npql):
tmp = linalg.norm(data["l"][i, :])
data["l"][i, :] = data["l"][i, :] / tmp
ubpql[i] = ubpql[i] / tmp
Apql = sparse((data["l"].flatten('F'),
(r_[arange(npql), arange(npql)], r_[ipql, ipql+ng])),
(npql, 2*ng))
ubpql = ubpql / baseMVA
else:
data["l"] = array([])
Apql = zeros((0, 2*ng))
ubpql = array([])
data["ipql"] = ipql
data["ipqh"] = ipqh
return Apqh, ubpqh, Apql, ubpql, data
0
Example 7
Project: PYPOWER Source File: makeAvl.py
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
0
Example 8
Project: PYPOWER Source File: makeAy.py
def makeAy(baseMVA, ng, gencost, pgbas, qgbas, ybas):
"""Make the A matrix and RHS for the CCV formulation.
Constructs the parameters for linear "basin constraints" on C{Pg}, C{Qg}
and C{Y} used by the CCV cost formulation, expressed as::
Ay * x <= by
where C{x} is the vector of optimization variables. The starting index
within the C{x} vector for the active, reactive sources and the C{y}
variables should be provided in arguments C{pgbas}, C{qgbas}, C{ybas}.
The number of generators is C{ng}.
Assumptions: All generators are in-service. Filter any generators
that are offline from the C{gencost} matrix before calling L{makeAy}.
Efficiency depends on C{Qg} variables being after C{Pg} variables, and
the C{y} variables must be the last variables within the vector C{x} for
the dimensions of the resulting C{Ay} to be conformable with C{x}.
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
## find all pwl cost rows in gencost, either real or reactive
iycost = find(gencost[:, MODEL] == PW_LINEAR)
## this is the number of extra "y" variables needed to model those costs
ny = iycost.shape[0]
if ny == 0:
Ay = zeros((0, ybas + ny - 1)) ## TODO: Check size (- 1)
by = array([])
return Ay, by
## if p(i),p(i+1),c(i),c(i+1) define one of the cost segments, then
## the corresponding constraint on Pg (or Qg) and Y is
## c(i+1) - c(i)
## Y >= c(i) + m * (Pg - p(i)), m = ---------------
## p(i+1) - p(i)
##
## this becomes m * Pg - Y <= m*p(i) - c(i)
## Form A matrix. Use two different loops, one for the PG/Qg coefs,
## then another for the y coefs so that everything is filled in the
## same order as the compressed column sparse format used by matlab
## this should be the quickest.
m = sum( gencost[iycost, NCOST].astype(int) ) ## total number of cost points
Ay = sparse((m - ny, ybas + ny - 1))
by = array([])
## First fill the Pg or Qg coefficients (since their columns come first)
## and the rhs
k = 0
for i in iycost:
ns = gencost[i, NCOST].astype(int) ## # of cost points segments = ns-1
p = gencost[i, COST:COST + 2 * ns - 1:2] / baseMVA
c = gencost[i, COST + 1:COST + 2 * ns:2]
m = diff(c) / diff(p) ## slopes for Pg (or Qg)
if any(diff(p) == 0):
print('makeAy: bad x axis data in row ##i of gencost matrix' % i)
b = m * p[:ns - 1] - c[:ns - 1] ## and rhs
by = r_[by, b]
if i > ng:
sidx = qgbas + (i - ng) - 1 ## this was for a q cost
else:
sidx = pgbas + i - 1 ## this was for a p cost
## FIXME: Bug in SciPy 0.7.2 prevents setting with a sequence
# Ay[k:k + ns - 1, sidx] = m
for ii, kk in enumerate(range(k, k + ns - 1)):
Ay[kk, sidx] = m[ii]
k = k + ns - 1
## Now fill the y columns with -1's
k = 0
j = 0
for i in iycost:
ns = gencost[i, NCOST].astype(int)
## FIXME: Bug in SciPy 0.7.2 prevents setting with a sequence
# Ay[k:k + ns - 1, ybas + j - 1] = -ones(ns - 1)
for kk in range(k, k + ns - 1):
Ay[kk, ybas + j - 1] = -1
k = k + ns - 1
j = j + 1
return Ay.tocsr(), by
0
Example 9
Project: PYPOWER Source File: makeBdc.py
def makeBdc(baseMVA, bus, branch):
"""Builds the B matrices and phase shift injections for DC power flow.
Returns the B matrices and phase shift injection vectors needed for a
DC power flow.
The bus real power injections are related to bus voltage angles by::
P = Bbus * Va + PBusinj
The real power flows at the from end the lines are related to the bus
voltage angles by::
Pf = Bf * Va + Pfinj
Does appropriate conversions to p.u.
@see: L{dcpf}
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
@author: Ray Zimmerman (PSERC Cornell)
"""
## constants
nb = bus.shape[0] ## number of buses
nl = branch.shape[0] ## number of lines
## check that bus numbers are equal to indices to bus (one set of bus nums)
if any(bus[:, BUS_I] != list(range(nb))):
stderr.write('makeBdc: buses must be numbered consecutively in '
'bus matrix\n')
## for each branch, compute the elements of the branch B matrix and the phase
## shift "quiescent" injections, where
##
## | Pf | | Bff Bft | | Vaf | | Pfinj |
## | | = | | * | | + | |
## | Pt | | Btf Btt | | Vat | | Ptinj |
##
stat = branch[:, BR_STATUS] ## ones at in-service branches
b = stat / branch[:, BR_X] ## series susceptance
tap = ones(nl) ## default tap ratio = 1
i = find(branch[:, TAP]) ## indices of non-zero tap ratios
tap[i] = branch[i, TAP] ## assign non-zero tap ratios
b = b / tap
## build connection matrix Cft = Cf - Ct for line and from - to buses
f = branch[:, F_BUS] ## list of "from" buses
t = branch[:, T_BUS] ## list of "to" buses
i = r_[range(nl), range(nl)] ## double set of row indices
## connection matrix
Cft = sparse((r_[ones(nl), -ones(nl)], (i, r_[f, t])), (nl, nb))
## build Bf such that Bf * Va is the vector of real branch powers injected
## at each branch's "from" bus
Bf = sparse((r_[b, -b], (i, r_[f, t])), shape = (nl, nb))## = spdiags(b, 0, nl, nl) * Cft
## build Bbus
Bbus = Cft.T * Bf
## build phase shift injection vectors
Pfinj = b * (-branch[:, SHIFT] * pi / 180) ## injected at the from bus ...
# Ptinj = -Pfinj ## and extracted at the to bus
Pbusinj = Cft.T * Pfinj ## Pbusinj = Cf * Pfinj + Ct * Ptinj
return Bbus, Bf, Pbusinj, Pfinj
0
Example 10
Project: PYPOWER Source File: makePTDF.py
def makePTDF(baseMVA, bus, branch, slack=None):
"""Builds the DC PTDF matrix for a given choice of slack.
Returns the DC PTDF matrix for a given choice of slack. The matrix is
C{nbr x nb}, where C{nbr} is the number of branches and C{nb} is the
number of buses. The C{slack} can be a scalar (single slack bus) or an
C{nb x 1} column vector of weights specifying the proportion of the
slack taken up at each bus. If the C{slack} is not specified the
reference bus is used by default.
For convenience, C{slack} can also be an C{nb x nb} matrix, where each
column specifies how the slack should be handled for injections
at that bus.
@see: L{makeLODF}
@author: Ray Zimmerman (PSERC Cornell)
"""
## use reference bus for slack by default
if slack is None:
slack = find(bus[:, BUS_TYPE] == REF)
slack = slack[0]
## set the slack bus to be used to compute initial PTDF
if isscalar(slack):
slack_bus = slack
else:
slack_bus = 0 ## use bus 1 for temp slack bus
nb = bus.shape[0]
nbr = branch.shape[0]
noref = arange(1, nb) ## use bus 1 for voltage angle reference
noslack = find(arange(nb) != slack_bus)
## check that bus numbers are equal to indices to bus (one set of bus numbers)
if any(bus[:, BUS_I] != arange(nb)):
stderr.write('makePTDF: buses must be numbered consecutively')
## compute PTDF for single slack_bus
Bbus, Bf, _, _ = makeBdc(baseMVA, bus, branch)
Bbus, Bf = Bbus.todense(), Bf.todense()
H = zeros((nbr, nb))
H[:, noslack] = solve( Bbus[ix_(noslack, noref)].T, Bf[:, noref].T ).T
# = Bf[:, noref] * inv(Bbus[ix_(noslack, noref)])
## distribute slack, if requested
if not isscalar(slack):
if len(slack.shape) == 1: ## slack is a vector of weights
slack = slack / sum(slack) ## normalize weights
## conceptually, we want to do ...
## H = H * (eye(nb, nb) - slack * ones((1, nb)))
## ... we just do it more efficiently
v = dot(H, slack)
for k in range(nb):
H[:, k] = H[:, k] - v
else:
H = dot(H, slack)
return H
0
Example 11
Project: PYPOWER Source File: makeSbus.py
def makeSbus(baseMVA, bus, gen):
"""Builds the vector of complex bus power injections.
Returns the vector of complex bus power injections, that is, generation
minus load. Power is expressed in per unit.
@see: L{makeYbus}
@author: Ray Zimmerman (PSERC Cornell)
"""
## generator info
on = find(gen[:, GEN_STATUS] > 0) ## which generators are on?
gbus = gen[on, GEN_BUS] ## what buses are they at?
## form net complex bus power injection vector
nb = bus.shape[0]
ngon = on.shape[0]
## connection matrix, element i, j is 1 if gen on(j) at bus i is ON
Cg = sparse((ones(ngon), (gbus, range(ngon))), (nb, ngon))
## power injected by gens plus power injected by loads converted to p.u.
Sbus = ( Cg * (gen[on, PG] + 1j * gen[on, QG]) -
(bus[:, PD] + 1j * bus[:, QD]) ) / baseMVA
return Sbus
0
Example 12
Project: PYPOWER Source File: modcost.py
def modcost(gencost, alpha, modtype='SCALE_F'):
"""Modifies generator costs by shifting or scaling (F or X).
For each generator cost F(X) (for real or reactive power) in
C{gencost}, this function modifies the cost by scaling or shifting
the function by C{alpha}, depending on the value of C{modtype}, and
and returns the modified C{gencost}. Rows of C{gencost} can be a mix
of polynomial or piecewise linear costs.
C{modtype} takes one of the 4 possible values (let F_alpha(X) denote the
the modified function)::
SCALE_F (default) : F_alpha(X) == F(X) * ALPHA
SCALE_X : F_alpha(X * ALPHA) == F(X)
SHIFT_F : F_alpha(X) == F(X) + ALPHA
SHIFT_X : F_alpha(X + ALPHA) == F(X)
@author: Ray Zimmerman (PSERC Cornell)
"""
gencost = gencost.copy()
ng, m = gencost.shape
if ng != 0:
ipwl = find(gencost[:, MODEL] == PW_LINEAR)
ipol = find(gencost[:, MODEL] == POLYNOMIAL)
c = gencost[ipol, COST:m]
if modtype == 'SCALE_F':
gencost[ipol, COST:m] = alpha * c
gencost[ipwl, COST+1:m:2] = alpha * gencost[ipwl, COST + 1:m:2]
elif modtype == 'SCALE_X':
for k in range(len(ipol)):
n = gencost[ipol[k], NCOST].astype(int)
for i in range(n):
gencost[ipol[k], COST + i] = c[k, i] / alpha**(n - i - 1)
gencost[ipwl, COST:m - 1:2] = alpha * gencost[ipwl, COST:m - 1:2]
elif modtype == 'SHIFT_F':
for k in range(len(ipol)):
n = gencost[ipol[k], NCOST].astype(int)
gencost[ipol[k], COST + n - 1] = alpha + c[k, n - 1]
gencost[ipwl, COST+1:m:2] = alpha + gencost[ipwl, COST + 1:m:2]
elif modtype == 'SHIFT_X':
for k in range(len(ipol)):
n = gencost[ipol[k], NCOST].astype(int)
gencost[ipol[k], COST:COST + n] = \
polyshift(c[k, :n].T, alpha).T
gencost[ipwl, COST:m - 1:2] = alpha + gencost[ipwl, COST:m - 1:2]
else:
sys.stderr.write('modcost: "%s" is not a valid modtype\n' % modtype)
return gencost
0
Example 13
Project: PYPOWER Source File: opf_costfcn.py
def opf_costfcn(x, om, return_hessian=False):
"""Evaluates objective function, gradient and Hessian for OPF.
Objective function evaluation routine for AC optimal power flow,
suitable for use with L{pips}. Computes objective function value,
gradient and Hessian.
@param x: optimization vector
@param om: OPF model object
@return: C{F} - value of objective function. C{df} - (optional) gradient
of objective function (column vector). C{d2f} - (optional) Hessian of
objective function (sparse matrix).
@see: L{opf_consfcn}, L{opf_hessfcn}
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
@author: Ray Zimmerman (PSERC Cornell)
"""
##----- initialize -----
## unpack data
ppc = om.get_ppc()
baseMVA, gen, gencost = ppc["baseMVA"], ppc["gen"], ppc["gencost"]
cp = om.get_cost_params()
N, Cw, H, dd, rh, kk, mm = \
cp["N"], cp["Cw"], cp["H"], cp["dd"], cp["rh"], cp["kk"], cp["mm"]
vv, _, _, _ = om.get_idx()
## problem dimensions
ng = gen.shape[0] ## number of dispatchable injections
ny = om.getN('var', 'y') ## number of piece-wise linear costs
nxyz = len(x) ## total number of control vars of all types
## grab Pg & Qg
Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]] ## active generation in p.u.
Qg = x[vv["i1"]["Qg"]:vv["iN"]["Qg"]] ## reactive generation in p.u.
##----- evaluate objective function -----
## polynomial cost of P and Q
# use totcost only on polynomial cost in the minimization problem
# formulation, pwl cost is the sum of the y variables.
ipol = find(gencost[:, MODEL] == POLYNOMIAL) ## poly MW and MVAr costs
xx = r_[ Pg, Qg ] * baseMVA
if any(ipol):
f = sum( totcost(gencost[ipol, :], xx[ipol]) ) ## cost of poly P or Q
else:
f = 0
## piecewise linear cost of P and Q
if ny > 0:
ccost = sparse((ones(ny),
(zeros(ny), arange(vv["i1"]["y"], vv["iN"]["y"]))),
(1, nxyz)).toarray().flatten()
f = f + dot(ccost, x)
else:
ccost = zeros(nxyz)
## generalized cost term
if issparse(N) and N.nnz > 0:
nw = N.shape[0]
r = N * x - rh ## Nx - rhat
iLT = find(r < -kk) ## below dead zone
iEQ = find((r == 0) & (kk == 0)) ## dead zone doesn't exist
iGT = find(r > kk) ## above dead zone
iND = r_[iLT, iEQ, iGT] ## rows that are Not in the Dead region
iL = find(dd == 1) ## rows using linear function
iQ = find(dd == 2) ## rows using quadratic function
LL = sparse((ones(len(iL)), (iL, iL)), (nw, nw))
QQ = sparse((ones(len(iQ)), (iQ, iQ)), (nw, nw))
kbar = sparse((r_[ones(len(iLT)), zeros(len(iEQ)), -ones(len(iGT))],
(iND, iND)), (nw, nw)) * kk
rr = r + kbar ## apply non-dead zone shift
M = sparse((mm[iND], (iND, iND)), (nw, nw)) ## dead zone or scale
diagrr = sparse((rr, (arange(nw), arange(nw))), (nw, nw))
## linear rows multiplied by rr(i), quadratic rows by rr(i)^2
w = M * (LL + QQ * diagrr) * rr
f = f + dot(w * H, w) / 2 + dot(Cw, w)
##----- evaluate cost gradient -----
## index ranges
iPg = range(vv["i1"]["Pg"], vv["iN"]["Pg"])
iQg = range(vv["i1"]["Qg"], vv["iN"]["Qg"])
## polynomial cost of P and Q
df_dPgQg = zeros(2 * ng) ## w.r.t p.u. Pg and Qg
df_dPgQg[ipol] = baseMVA * polycost(gencost[ipol, :], xx[ipol], 1)
df = zeros(nxyz)
df[iPg] = df_dPgQg[:ng]
df[iQg] = df_dPgQg[ng:ng + ng]
## piecewise linear cost of P and Q
df = df + ccost # The linear cost row is additive wrt any nonlinear cost.
## generalized cost term
if issparse(N) and N.nnz > 0:
HwC = H * w + Cw
AA = N.T * M * (LL + 2 * QQ * diagrr)
df = df + AA * HwC
## numerical check
if 0: ## 1 to check, 0 to skip check
ddff = zeros(df.shape)
step = 1e-7
tol = 1e-3
for k in range(len(x)):
xx = x
xx[k] = xx[k] + step
ddff[k] = (opf_costfcn(xx, om) - f) / step
if max(abs(ddff - df)) > tol:
idx = find(abs(ddff - df) == max(abs(ddff - df)))
print('Mismatch in gradient')
print('idx df(num) df diff')
print('%4d%16g%16g%16g' %
(range(len(df)), ddff.T, df.T, abs(ddff - df).T))
print('MAX')
print('%4d%16g%16g%16g' %
(idx.T, ddff[idx].T, df[idx].T,
abs(ddff[idx] - df[idx]).T))
if not return_hessian:
return f, df
## ---- evaluate cost Hessian -----
pcost = gencost[range(ng), :]
if gencost.shape[0] > ng:
qcost = gencost[ng + 1:2 * ng, :]
else:
qcost = array([])
## polynomial generator costs
d2f_dPg2 = zeros(ng) ## w.r.t. p.u. Pg
d2f_dQg2 = zeros(ng) ## w.r.t. p.u. Qg
ipolp = find(pcost[:, MODEL] == POLYNOMIAL)
d2f_dPg2[ipolp] = \
baseMVA**2 * polycost(pcost[ipolp, :], Pg[ipolp]*baseMVA, 2)
if any(qcost): ## Qg is not free
ipolq = find(qcost[:, MODEL] == POLYNOMIAL)
d2f_dQg2[ipolq] = \
baseMVA**2 * polycost(qcost[ipolq, :], Qg[ipolq] * baseMVA, 2)
i = r_[iPg, iQg].T
d2f = sparse((r_[d2f_dPg2, d2f_dQg2], (i, i)), (nxyz, nxyz))
## generalized cost
if N is not None and issparse(N):
d2f = d2f + AA * H * AA.T + 2 * N.T * M * QQ * \
sparse((HwC, (range(nw), range(nw))), (nw, nw)) * N
return f, df, d2f
0
Example 14
Project: PYPOWER Source File: opf_hessfcn.py
def opf_hessfcn(x, lmbda, om, Ybus, Yf, Yt, ppopt, il=None, cost_mult=1.0):
"""Evaluates Hessian of Lagrangian for AC OPF.
Hessian evaluation function for AC optimal power flow, suitable
for use with L{pips}.
Examples::
Lxx = opf_hessfcn(x, lmbda, om, Ybus, Yf, Yt, ppopt)
Lxx = opf_hessfcn(x, lmbda, om, Ybus, Yf, Yt, ppopt, il)
Lxx = opf_hessfcn(x, lmbda, om, Ybus, Yf, Yt, ppopt, il, cost_mult)
@param x: optimization vector
@param lmbda: C{eqnonlin} - Lagrange multipliers on power balance
equations. C{ineqnonlin} - Kuhn-Tucker multipliers on constrained
branch flows.
@param om: OPF model object
@param Ybus: bus admittance matrix
@param Yf: admittance matrix for "from" end of constrained branches
@param Yt: admittance matrix for "to" end of constrained branches
@param ppopt: PYPOWER options vector
@param il: (optional) vector of branch indices corresponding to
branches with flow limits (all others are assumed to be unconstrained).
The default is C{range(nl)} (all branches). C{Yf} and C{Yt} contain
only the rows corresponding to C{il}.
@param cost_mult: (optional) Scale factor to be applied to the cost
(default = 1).
@return: Hessian of the Lagrangian.
@see: L{opf_costfcn}, L{opf_consfcn}
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
##----- initialize -----
## unpack data
ppc = om.get_ppc()
baseMVA, bus, gen, branch, gencost = \
ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
cp = om.get_cost_params()
N, Cw, H, dd, rh, kk, mm = \
cp["N"], cp["Cw"], cp["H"], cp["dd"], cp["rh"], cp["kk"], cp["mm"]
vv, _, _, _ = om.get_idx()
## unpack needed parameters
nb = bus.shape[0] ## number of buses
nl = branch.shape[0] ## number of branches
ng = gen.shape[0] ## number of dispatchable injections
nxyz = len(x) ## total number of control vars of all types
## set default constrained lines
if il is None:
il = arange(nl) ## all lines have limits by default
nl2 = len(il) ## number of constrained lines
## grab Pg & Qg
Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]] ## active generation in p.u.
Qg = x[vv["i1"]["Qg"]:vv["iN"]["Qg"]] ## reactive generation in p.u.
## put Pg & Qg back in gen
gen[:, PG] = Pg * baseMVA ## active generation in MW
gen[:, QG] = Qg * baseMVA ## reactive generation in MVAr
## reconstruct V
Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
Vm = x[vv["i1"]["Vm"]:vv["iN"]["Vm"]]
V = Vm * exp(1j * Va)
nxtra = nxyz - 2 * nb
pcost = gencost[arange(ng), :]
if gencost.shape[0] > ng:
qcost = gencost[arange(ng, 2 * ng), :]
else:
qcost = array([])
## ----- evaluate d2f -----
d2f_dPg2 = zeros(ng)#sparse((ng, 1)) ## w.r.t. p.u. Pg
d2f_dQg2 = zeros(ng)#sparse((ng, 1)) ## w.r.t. p.u. Qg
ipolp = find(pcost[:, MODEL] == POLYNOMIAL)
d2f_dPg2[ipolp] = \
baseMVA**2 * polycost(pcost[ipolp, :], Pg[ipolp] * baseMVA, 2)
if any(qcost): ## Qg is not free
ipolq = find(qcost[:, MODEL] == POLYNOMIAL)
d2f_dQg2[ipolq] = \
baseMVA**2 * polycost(qcost[ipolq, :], Qg[ipolq] * baseMVA, 2)
i = r_[arange(vv["i1"]["Pg"], vv["iN"]["Pg"]),
arange(vv["i1"]["Qg"], vv["iN"]["Qg"])]
# d2f = sparse((vstack([d2f_dPg2, d2f_dQg2]).toarray().flatten(),
# (i, i)), shape=(nxyz, nxyz))
d2f = sparse((r_[d2f_dPg2, d2f_dQg2], (i, i)), (nxyz, nxyz))
## generalized cost
if issparse(N) and N.nnz > 0:
nw = N.shape[0]
r = N * x - rh ## Nx - rhat
iLT = find(r < -kk) ## below dead zone
iEQ = find((r == 0) & (kk == 0)) ## dead zone doesn't exist
iGT = find(r > kk) ## above dead zone
iND = r_[iLT, iEQ, iGT] ## rows that are Not in the Dead region
iL = find(dd == 1) ## rows using linear function
iQ = find(dd == 2) ## rows using quadratic function
LL = sparse((ones(len(iL)), (iL, iL)), (nw, nw))
QQ = sparse((ones(len(iQ)), (iQ, iQ)), (nw, nw))
kbar = sparse((r_[ones(len(iLT)), zeros(len(iEQ)), -ones(len(iGT))],
(iND, iND)), (nw, nw)) * kk
rr = r + kbar ## apply non-dead zone shift
M = sparse((mm[iND], (iND, iND)), (nw, nw)) ## dead zone or scale
diagrr = sparse((rr, (arange(nw), arange(nw))), (nw, nw))
## linear rows multiplied by rr(i), quadratic rows by rr(i)^2
w = M * (LL + QQ * diagrr) * rr
HwC = H * w + Cw
AA = N.T * M * (LL + 2 * QQ * diagrr)
d2f = d2f + AA * H * AA.T + 2 * N.T * M * QQ * \
sparse((HwC, (arange(nw), arange(nw))), (nw, nw)) * N
d2f = d2f * cost_mult
##----- evaluate Hessian of power balance constraints -----
nlam = len(lmbda["eqnonlin"]) / 2
lamP = lmbda["eqnonlin"][:nlam]
lamQ = lmbda["eqnonlin"][nlam:nlam + nlam]
Gpaa, Gpav, Gpva, Gpvv = d2Sbus_dV2(Ybus, V, lamP)
Gqaa, Gqav, Gqva, Gqvv = d2Sbus_dV2(Ybus, V, lamQ)
d2G = vstack([
hstack([
vstack([hstack([Gpaa, Gpav]),
hstack([Gpva, Gpvv])]).real +
vstack([hstack([Gqaa, Gqav]),
hstack([Gqva, Gqvv])]).imag,
sparse((2 * nb, nxtra))]),
hstack([
sparse((nxtra, 2 * nb)),
sparse((nxtra, nxtra))
])
], "csr")
##----- evaluate Hessian of flow constraints -----
nmu = len(lmbda["ineqnonlin"]) / 2
muF = lmbda["ineqnonlin"][:nmu]
muT = lmbda["ineqnonlin"][nmu:nmu + nmu]
if ppopt['OPF_FLOW_LIM'] == 2: ## current
dIf_dVa, dIf_dVm, dIt_dVa, dIt_dVm, If, It = dIbr_dV(Yf, Yt, V)
Hfaa, Hfav, Hfva, Hfvv = d2AIbr_dV2(dIf_dVa, dIf_dVm, If, Yf, V, muF)
Htaa, Htav, Htva, Htvv = d2AIbr_dV2(dIt_dVa, dIt_dVm, It, Yt, V, muT)
else:
f = branch[il, F_BUS].astype(int) ## list of "from" buses
t = branch[il, T_BUS].astype(int) ## list of "to" buses
## connection matrix for line & from buses
Cf = sparse((ones(nl2), (arange(nl2), f)), (nl2, nb))
## connection matrix for line & to buses
Ct = sparse((ones(nl2), (arange(nl2), t)), (nl2, nb))
dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St = \
dSbr_dV(branch[il,:], Yf, Yt, V)
if ppopt['OPF_FLOW_LIM'] == 1: ## real power
Hfaa, Hfav, Hfva, Hfvv = d2ASbr_dV2(dSf_dVa.real, dSf_dVm.real,
Sf.real, Cf, Yf, V, muF)
Htaa, Htav, Htva, Htvv = d2ASbr_dV2(dSt_dVa.real, dSt_dVm.real,
St.real, Ct, Yt, V, muT)
else: ## apparent power
Hfaa, Hfav, Hfva, Hfvv = \
d2ASbr_dV2(dSf_dVa, dSf_dVm, Sf, Cf, Yf, V, muF)
Htaa, Htav, Htva, Htvv = \
d2ASbr_dV2(dSt_dVa, dSt_dVm, St, Ct, Yt, V, muT)
d2H = vstack([
hstack([
vstack([hstack([Hfaa, Hfav]),
hstack([Hfva, Hfvv])]) +
vstack([hstack([Htaa, Htav]),
hstack([Htva, Htvv])]),
sparse((2 * nb, nxtra))
]),
hstack([
sparse((nxtra, 2 * nb)),
sparse((nxtra, nxtra))
])
], "csr")
##----- do numerical check using (central) finite differences -----
if 0:
nx = len(x)
step = 1e-5
num_d2f = sparse((nx, nx))
num_d2G = sparse((nx, nx))
num_d2H = sparse((nx, nx))
for i in range(nx):
xp = x
xm = x
xp[i] = x[i] + step / 2
xm[i] = x[i] - step / 2
# evaluate cost & gradients
_, dfp = opf_costfcn(xp, om)
_, dfm = opf_costfcn(xm, om)
# evaluate constraints & gradients
_, _, dHp, dGp = opf_consfcn(xp, om, Ybus, Yf, Yt, ppopt, il)
_, _, dHm, dGm = opf_consfcn(xm, om, Ybus, Yf, Yt, ppopt, il)
num_d2f[:, i] = cost_mult * (dfp - dfm) / step
num_d2G[:, i] = (dGp - dGm) * lmbda["eqnonlin"] / step
num_d2H[:, i] = (dHp - dHm) * lmbda["ineqnonlin"] / step
d2f_err = max(max(abs(d2f - num_d2f)))
d2G_err = max(max(abs(d2G - num_d2G)))
d2H_err = max(max(abs(d2H - num_d2H)))
if d2f_err > 1e-6:
print('Max difference in d2f: %g' % d2f_err)
if d2G_err > 1e-5:
print('Max difference in d2G: %g' % d2G_err)
if d2H_err > 1e-6:
print('Max difference in d2H: %g' % d2H_err)
return d2f + d2G + d2H
0
Example 15
Project: PYPOWER Source File: opf_model.py
def compute_cost(self, x, name=None):
""" Computes a user-defined cost.
Computes the value of a user defined cost, either for all user
defined costs or for a named set of costs. Requires calling
L{build_cost_params} first to build the full set of parameters.
Let C{x} be the full set of optimization variables and C{f_u(x, cp)} be
the user-defined cost at C{x}, corresponding to the set of cost
parameters in the C{cp} dict returned by L{get_cost_params}, where
C{cp} is a dict with the following fields::
N - nw x nx sparse matrix
Cw - nw x 1 vector
H - nw x nw sparse matrix (optional, all zeros by default)
dd, mm - nw x 1 vectors (optional, all ones by default)
rh, kk - nw x 1 vectors (optional, all zeros by default)
These parameters are used as follows to compute C{f_u(x, cp)}::
R = N*x - rh
/ kk(i), R(i) < -kk(i)
K(i) = < 0, -kk(i) <= R(i) <= kk(i)
\ -kk(i), R(i) > kk(i)
RR = R + K
U(i) = / 0, -kk(i) <= R(i) <= kk(i)
\ 1, otherwise
DDL(i) = / 1, dd(i) = 1
\ 0, otherwise
DDQ(i) = / 1, dd(i) = 2
\ 0, otherwise
Dl = diag(mm) * diag(U) * diag(DDL)
Dq = diag(mm) * diag(U) * diag(DDQ)
w = (Dl + Dq * diag(RR)) * RR
F_U(X, CP) = 1/2 * w'*H*w + Cw'*w
"""
if name is None:
cp = self.get_cost_params()
else:
cp = self.get_cost_params(name)
N, Cw, H, dd, rh, kk, mm = \
cp["N"], cp["Cw"], cp["H"], cp["dd"], cp["rh"], cp["kk"], cp["mm"]
nw = N.shape[0]
r = N * x - rh ## Nx - rhat
iLT = find(r < -kk) ## below dead zone
iEQ = find((r == 0) & (kk == 0)) ## dead zone doesn't exist
iGT = find(r > kk) ## above dead zone
iND = r_[iLT, iEQ, iGT] ## rows that are Not in the Dead region
iL = find(dd == 1) ## rows using linear function
iQ = find(dd == 2) ## rows using quadratic function
LL = sparse((ones(len(iL)), (iL, iL)), (nw, nw))
QQ = sparse((ones(len(iQ)), (iQ, iQ)), (nw, nw))
kbar = sparse((r_[ ones(len(iLT)),
zeros(len(iEQ)),
-ones(len(iGT))], (iND, iND)), (nw, nw)) * kk
rr = r + kbar ## apply non-dead zone shift
M = sparse((mm[iND], (iND, iND)), (nw, nw)) ## dead zone or scale
diagrr = sparse((rr, (arange(nw), arange(nw))), (nw, nw))
## linear rows multiplied by rr(i), quadratic rows by rr(i)^2
w = M * (LL + QQ * diagrr) * rr
f = dot(w * H, w) / 2 + dot(Cw, w)
return f
0
Example 16
Project: PYPOWER Source File: opf_setup.py
def opf_setup(ppc, ppopt):
"""Constructs an OPF model object from a PYPOWER case dict.
Assumes that ppc is a PYPOWER case dict with internal indexing,
all equipment in-service, etc.
@see: L{opf}, L{ext2int}, L{opf_execute}
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
## options
dc = ppopt['PF_DC'] ## 1 = DC OPF, 0 = AC OPF
alg = ppopt['OPF_ALG']
verbose = ppopt['VERBOSE']
## data dimensions
nb = ppc['bus'].shape[0] ## number of buses
nl = ppc['branch'].shape[0] ## number of branches
ng = ppc['gen'].shape[0] ## number of dispatchable injections
if 'A' in ppc:
nusr = ppc['A'].shape[0] ## number of linear user constraints
else:
nusr = 0
if 'N' in ppc:
nw = ppc['N'].shape[0] ## number of general cost vars, w
else:
nw = 0
if dc:
## ignore reactive costs for DC
ppc['gencost'], _ = pqcost(ppc['gencost'], ng)
## reduce A and/or N from AC dimensions to DC dimensions, if needed
if nusr or nw:
acc = r_[nb + arange(nb), 2 * nb + ng + arange(ng)] ## Vm and Qg columns
if nusr and (ppc['A'].shape[1] >= 2*nb + 2*ng):
## make sure there aren't any constraints on Vm or Qg
if ppc['A'][:, acc].nnz > 0:
stderr.write('opf_setup: attempting to solve DC OPF with user constraints on Vm or Qg\n')
# FIXME: delete sparse matrix columns
bcc = delete(arange(ppc['A'].shape[1]), acc)
ppc['A'] = ppc['A'].tolil()[:, bcc].tocsr() ## delete Vm and Qg columns
if nw and (ppc['N'].shape[1] >= 2*nb + 2*ng):
## make sure there aren't any costs on Vm or Qg
if ppc['N'][:, acc].nnz > 0:
ii, _ = nonzero(ppc['N'][:, acc])
_, ii = unique(ii, return_index=True) ## indices of w with potential non-zero cost terms from Vm or Qg
if any(ppc['Cw'][ii]) | ( ('H' in ppc) & (len(ppc['H']) > 0) &
any(any(ppc['H'][:, ii])) ):
stderr.write('opf_setup: attempting to solve DC OPF with user costs on Vm or Qg\n')
# FIXME: delete sparse matrix columns
bcc = delete(arange(ppc['N'].shape[1]), acc)
ppc['N'] = ppc['N'].tolil()[:, bcc].tocsr() ## delete Vm and Qg columns
## convert single-block piecewise-linear costs into linear polynomial cost
pwl1 = find((ppc['gencost'][:, MODEL] == PW_LINEAR) & (ppc['gencost'][:, NCOST] == 2))
# p1 = array([])
if len(pwl1) > 0:
x0 = ppc['gencost'][pwl1, COST]
y0 = ppc['gencost'][pwl1, COST + 1]
x1 = ppc['gencost'][pwl1, COST + 2]
y1 = ppc['gencost'][pwl1, COST + 3]
m = (y1 - y0) / (x1 - x0)
b = y0 - m * x0
ppc['gencost'][pwl1, MODEL] = POLYNOMIAL
ppc['gencost'][pwl1, NCOST] = 2
ppc['gencost'][pwl1, COST:COST + 2] = r_[m, b]
## create (read-only) copies of individual fields for convenience
baseMVA, bus, gen, branch, gencost, _, lbu, ubu, ppopt, \
_, fparm, H, Cw, z0, zl, zu, userfcn, _ = opf_args(ppc, ppopt)
## warn if there is more than one reference bus
refs = find(bus[:, BUS_TYPE] == REF)
if len(refs) > 1 and verbose > 0:
errstr = '\nopf_setup: Warning: Multiple reference buses.\n' + \
' For a system with islands, a reference bus in each island\n' + \
' may help convergence, but in a fully connected system such\n' + \
' a situation is probably not reasonable.\n\n'
stdout.write(errstr)
## set up initial variables and bounds
gbus = gen[:, GEN_BUS].astype(int)
Va = bus[:, VA] * (pi / 180.0)
Vm = bus[:, VM].copy()
Vm[gbus] = gen[:, VG] ## buses with gens, init Vm from gen data
Pg = gen[:, PG] / baseMVA
Qg = gen[:, QG] / baseMVA
Pmin = gen[:, PMIN] / baseMVA
Pmax = gen[:, PMAX] / baseMVA
Qmin = gen[:, QMIN] / baseMVA
Qmax = gen[:, QMAX] / baseMVA
if dc: ## DC model
## more problem dimensions
nv = 0 ## number of voltage magnitude vars
nq = 0 ## number of Qg vars
q1 = array([]) ## index of 1st Qg column in Ay
## power mismatch constraints
B, Bf, Pbusinj, Pfinj = makeBdc(baseMVA, bus, branch)
neg_Cg = sparse((-ones(ng), (gen[:, GEN_BUS], arange(ng))), (nb, ng)) ## Pbus w.r.t. Pg
Amis = hstack([B, neg_Cg], 'csr')
bmis = -(bus[:, PD] + bus[:, GS]) / baseMVA - Pbusinj
## branch flow constraints
il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
nl2 = len(il) ## number of constrained lines
lpf = -Inf * ones(nl2)
upf = branch[il, RATE_A] / baseMVA - Pfinj[il]
upt = branch[il, RATE_A] / baseMVA + Pfinj[il]
user_vars = ['Va', 'Pg']
ycon_vars = ['Pg', 'y']
else: ## AC model
## more problem dimensions
nv = nb ## number of voltage magnitude vars
nq = ng ## number of Qg vars
q1 = ng ## index of 1st Qg column in Ay
## dispatchable load, constant power factor constraints
Avl, lvl, uvl, _ = makeAvl(baseMVA, gen)
## generator PQ capability curve constraints
Apqh, ubpqh, Apql, ubpql, Apqdata = makeApq(baseMVA, gen)
user_vars = ['Va', 'Vm', 'Pg', 'Qg']
ycon_vars = ['Pg', 'Qg', 'y']
## voltage angle reference constraints
Vau = Inf * ones(nb)
Val = -Vau
Vau[refs] = Va[refs]
Val[refs] = Va[refs]
## branch voltage angle difference limits
Aang, lang, uang, iang = makeAang(baseMVA, branch, nb, ppopt)
## basin constraints for piece-wise linear gen cost variables
if alg == 545 or alg == 550: ## SC-PDIPM or TRALM, no CCV cost vars
ny = 0
Ay = None
by = array([])
else:
ipwl = find(gencost[:, MODEL] == PW_LINEAR) ## piece-wise linear costs
ny = ipwl.shape[0] ## number of piece-wise linear cost vars
Ay, by = makeAy(baseMVA, ng, gencost, 1, q1, 1+ng+nq)
if any((gencost[:, MODEL] != POLYNOMIAL) & (gencost[:, MODEL] != PW_LINEAR)):
stderr.write('opf_setup: some generator cost rows have invalid MODEL value\n')
## more problem dimensions
nx = nb+nv + ng+nq; ## number of standard OPF control variables
if nusr:
nz = ppc['A'].shape[1] - nx ## number of user z variables
if nz < 0:
stderr.write('opf_setup: user supplied A matrix must have at least %d columns.\n' % nx)
else:
nz = 0 ## number of user z variables
if nw: ## still need to check number of columns of N
if ppc['N'].shape[1] != nx:
stderr.write('opf_setup: user supplied N matrix must have %d columns.\n' % nx)
## construct OPF model object
om = opf_model(ppc)
if len(pwl1) > 0:
om.userdata('pwl1', pwl1)
if dc:
om.userdata('Bf', Bf)
om.userdata('Pfinj', Pfinj)
om.userdata('iang', iang)
om.add_vars('Va', nb, Va, Val, Vau)
om.add_vars('Pg', ng, Pg, Pmin, Pmax)
om.add_constraints('Pmis', Amis, bmis, bmis, ['Va', 'Pg']) ## nb
om.add_constraints('Pf', Bf[il, :], lpf, upf, ['Va']) ## nl
om.add_constraints('Pt', -Bf[il, :], lpf, upt, ['Va']) ## nl
om.add_constraints('ang', Aang, lang, uang, ['Va']) ## nang
else:
om.userdata('Apqdata', Apqdata)
om.userdata('iang', iang)
om.add_vars('Va', nb, Va, Val, Vau)
om.add_vars('Vm', nb, Vm, bus[:, VMIN], bus[:, VMAX])
om.add_vars('Pg', ng, Pg, Pmin, Pmax)
om.add_vars('Qg', ng, Qg, Qmin, Qmax)
om.add_constraints('Pmis', nb, 'nonlinear')
om.add_constraints('Qmis', nb, 'nonlinear')
om.add_constraints('Sf', nl, 'nonlinear')
om.add_constraints('St', nl, 'nonlinear')
om.add_constraints('PQh', Apqh, array([]), ubpqh, ['Pg', 'Qg']) ## npqh
om.add_constraints('PQl', Apql, array([]), ubpql, ['Pg', 'Qg']) ## npql
om.add_constraints('vl', Avl, lvl, uvl, ['Pg', 'Qg']) ## nvl
om.add_constraints('ang', Aang, lang, uang, ['Va']) ## nang
## y vars, constraints for piece-wise linear gen costs
if ny > 0:
om.add_vars('y', ny)
om.add_constraints('ycon', Ay, array([]), by, ycon_vars) ## ncony
## add user vars, constraints and costs (as specified via A, ..., N, ...)
if nz > 0:
om.add_vars('z', nz, z0, zl, zu)
user_vars.append('z')
if nusr:
om.add_constraints('usr', ppc['A'], lbu, ubu, user_vars) ## nusr
if nw:
user_cost = {}
user_cost['N'] = ppc['N']
user_cost['Cw'] = Cw
if len(fparm) > 0:
user_cost['dd'] = fparm[:, 0]
user_cost['rh'] = fparm[:, 1]
user_cost['kk'] = fparm[:, 2]
user_cost['mm'] = fparm[:, 3]
# if len(H) > 0:
user_cost['H'] = H
om.add_costs('usr', user_cost, user_vars)
## execute userfcn callbacks for 'formulation' stage
run_userfcn(userfcn, 'formulation', om)
return om
0
Example 17
Project: PYPOWER Source File: pfsoln.py
def pfsoln(baseMVA, bus0, gen0, branch0, Ybus, Yf, Yt, V, ref, pv, pq):
"""Updates bus, gen, branch data structures to match power flow soln.
@author: Ray Zimmerman (PSERC Cornell)
"""
## initialize return values
bus = bus0
gen = gen0
branch = branch0
##----- update bus voltages -----
bus[:, VM] = abs(V)
bus[:, VA] = angle(V) * 180 / pi
##----- update Qg for all gens and Pg for slack bus(es) -----
## generator info
on = find(gen[:, GEN_STATUS] > 0) ## which generators are on?
gbus = gen[on, GEN_BUS].astype(int) ## what buses are they at?
## compute total injected bus powers
Sbus = V[gbus] * conj(Ybus[gbus, :] * V)
## update Qg for all generators
gen[:, QG] = zeros(gen.shape[0]) ## zero out all Qg
gen[on, QG] = Sbus.imag * baseMVA + bus[gbus, QD] ## inj Q + local Qd
## ... at this point any buses with more than one generator will have
## the total Q dispatch for the bus assigned to each generator. This
## must be split between them. We do it first equally, then in proportion
## to the reactive range of the generator.
if len(on) > 1:
## build connection matrix, element i, j is 1 if gen on(i) at bus j is ON
nb = bus.shape[0]
ngon = on.shape[0]
Cg = csr_matrix((ones(ngon), (range(ngon), gbus)), (ngon, nb))
## divide Qg by number of generators at the bus to distribute equally
ngg = Cg * Cg.sum(0).T ## ngon x 1, number of gens at this gen's bus
ngg = asarray(ngg).flatten() # 1D array
gen[on, QG] = gen[on, QG] / ngg
## divide proportionally
Cmin = csr_matrix((gen[on, QMIN], (range(ngon), gbus)), (ngon, nb))
Cmax = csr_matrix((gen[on, QMAX], (range(ngon), gbus)), (ngon, nb))
Qg_tot = Cg.T * gen[on, QG]## nb x 1 vector of total Qg at each bus
Qg_min = Cmin.sum(0).T ## nb x 1 vector of min total Qg at each bus
Qg_max = Cmax.sum(0).T ## nb x 1 vector of max total Qg at each bus
Qg_min = asarray(Qg_min).flatten() # 1D array
Qg_max = asarray(Qg_max).flatten() # 1D array
## gens at buses with Qg range = 0
ig = find(Cg * Qg_min == Cg * Qg_max)
Qg_save = gen[on[ig], QG]
gen[on, QG] = gen[on, QMIN] + \
(Cg * ((Qg_tot - Qg_min) / (Qg_max - Qg_min + EPS))) * \
(gen[on, QMAX] - gen[on, QMIN]) ## ^ avoid div by 0
gen[on[ig], QG] = Qg_save ## (terms are mult by 0 anyway)
## update Pg for slack bus(es)
## inj P + local Pd
for k in range(len(ref)):
refgen = find(gbus == ref[k]) ## which is(are) the reference gen(s)?
gen[on[refgen[0]], PG] = \
Sbus[refgen[0]].real * baseMVA + bus[ref[k], PD]
if len(refgen) > 1: ## more than one generator at this ref bus
## subtract off what is generated by other gens at this bus
gen[on[refgen[0]], PG] = \
gen[on[refgen[0]], PG] - sum(gen[on[refgen[1:len(refgen)]], PG])
##----- update/compute branch power flows -----
out = find(branch[:, BR_STATUS] == 0) ## out-of-service branches
br = find(branch[:, BR_STATUS]).astype(int) ## in-service branches
## complex power at "from" bus
Sf = V[ branch[br, F_BUS].astype(int) ] * conj(Yf[br, :] * V) * baseMVA
## complex power injected at "to" bus
St = V[ branch[br, T_BUS].astype(int) ] * conj(Yt[br, :] * V) * baseMVA
branch[ ix_(br, [PF, QF, PT, QT]) ] = c_[Sf.real, Sf.imag, St.real, St.imag]
branch[ ix_(out, [PF, QF, PT, QT]) ] = zeros((len(out), 4))
return bus, gen, branch
0
Example 18
Project: PYPOWER Source File: pips.py
def pips(f_fcn, x0=None, A=None, l=None, u=None, xmin=None, xmax=None,
gh_fcn=None, hess_fcn=None, opt=None):
"""Primal-dual interior point method for NLP (nonlinear programming).
Minimize a function F(X) beginning from a starting point M{x0}, subject to
optional linear and nonlinear constraints and variable bounds::
min f(x)
x
subject to::
g(x) = 0 (nonlinear equalities)
h(x) <= 0 (nonlinear inequalities)
l <= A*x <= u (linear constraints)
xmin <= x <= xmax (variable bounds)
Note: The calling syntax is almost identical to that of FMINCON from
MathWorks' Optimization Toolbox. The main difference is that the linear
constraints are specified with C{A}, C{L}, C{U} instead of C{A}, C{B},
C{Aeq}, C{Beq}. The functions for evaluating the objective function,
constraints and Hessian are identical.
Example from U{http://en.wikipedia.org/wiki/Nonlinear_programming}:
>>> from numpy import array, r_, float64, dot
>>> from scipy.sparse import csr_matrix
>>> def f2(x):
... f = -x[0] * x[1] - x[1] * x[2]
... df = -r_[x[1], x[0] + x[2], x[1]]
... # actually not used since 'hess_fcn' is provided
... d2f = -array([[0, 1, 0], [1, 0, 1], [0, 1, 0]], float64)
... return f, df, d2f
>>> def gh2(x):
... h = dot(array([[1, -1, 1],
... [1, 1, 1]]), x**2) + array([-2.0, -10.0])
... dh = 2 * csr_matrix(array([[ x[0], x[0]],
... [-x[1], x[1]],
... [ x[2], x[2]]]))
... g = array([])
... dg = None
... return h, g, dh, dg
>>> def hess2(x, lam, cost_mult=1):
... mu = lam["ineqnonlin"]
... a = r_[dot(2 * array([1, 1]), mu), -1, 0]
... b = r_[-1, dot(2 * array([-1, 1]), mu),-1]
... c = r_[0, -1, dot(2 * array([1, 1]), mu)]
... Lxx = csr_matrix(array([a, b, c]))
... return Lxx
>>> x0 = array([1, 1, 0], float64)
>>> solution = pips(f2, x0, gh_fcn=gh2, hess_fcn=hess2)
>>> round(solution["f"], 11) == -7.07106725919
True
>>> solution["output"]["iterations"]
8
Ported by Richard Lincoln from the MATLAB Interior Point Solver (MIPS)
(v1.9) by Ray Zimmerman. MIPS is distributed as part of the MATPOWER
project, developed at the Power System Engineering Research Center (PSERC) (PSERC),
Cornell. See U{http://www.pserc.cornell.edu/matpower/} for more info.
MIPS was ported by Ray Zimmerman from C code written by H. Wang for his
PhD dissertation:
- "On the Computation and Application of Multi-period
Security-Constrained Optimal Power Flow for Real-time
Electricity Market Operations", Cornell University, May 2007.
See also:
- H. Wang, C. E. Murillo-Sanchez, R. D. Zimmerman, R. J. Thomas,
"On Computational Issues of Market-Based Optimal Power Flow",
IEEE Transactions on Power Systems, Vol. 22, No. 3, Aug. 2007,
pp. 1185-1193.
All parameters are optional except C{f_fcn} and C{x0}.
@param f_fcn: Function that evaluates the objective function, its gradients
and Hessian for a given value of M{x}. If there are
nonlinear constraints, the Hessian information is provided
by the 'hess_fcn' argument and is not required here.
@type f_fcn: callable
@param x0: Starting value of optimization vector M{x}.
@type x0: array
@param A: Optional linear constraints.
@type A: csr_matrix
@param l: Optional linear constraints. Default values are M{-Inf}.
@type l: array
@param u: Optional linear constraints. Default values are M{Inf}.
@type u: array
@param xmin: Optional lower bounds on the M{x} variables, defaults are
M{-Inf}.
@type xmin: array
@param xmax: Optional upper bounds on the M{x} variables, defaults are
M{Inf}.
@type xmax: array
@param gh_fcn: Function that evaluates the optional nonlinear constraints
and their gradients for a given value of M{x}.
@type gh_fcn: callable
@param hess_fcn: Handle to function that computes the Hessian of the
Lagrangian for given values of M{x}, M{lambda} and M{mu},
where M{lambda} and M{mu} are the multipliers on the
equality and inequality constraints, M{g} and M{h},
respectively.
@type hess_fcn: callable
@param opt: optional options dictionary with the following keys, all of
which are also optional (default values shown in parentheses)
- C{verbose} (False) - Controls level of progress output
displayed
- C{feastol} (1e-6) - termination tolerance for feasibility
condition
- C{gradtol} (1e-6) - termination tolerance for gradient
condition
- C{comptol} (1e-6) - termination tolerance for
complementarity condition
- C{costtol} (1e-6) - termination tolerance for cost
condition
- C{max_it} (150) - maximum number of iterations
- C{step_control} (False) - set to True to enable step-size
control
- C{max_red} (20) - maximum number of step-size reductions if
step-control is on
- C{cost_mult} (1.0) - cost multiplier used to scale the
objective function for improved conditioning. Note: This
value is also passed as the 3rd argument to the Hessian
evaluation function so that it can appropriately scale the
objective function term in the Hessian of the Lagrangian.
@type opt: dict
@rtype: dict
@return: The solution dictionary has the following keys:
- C{x} - solution vector
- C{f} - final objective function value
- C{converged} - exit status
- True = first order optimality conditions satisfied
- False = maximum number of iterations reached
- None = numerically failed
- C{output} - output dictionary with keys:
- C{iterations} - number of iterations performed
- C{hist} - list of arrays with trajectories of the
following: feascond, gradcond, compcond, costcond, gamma,
stepsize, obj, alphap, alphad
- C{message} - exit message
- C{lmbda} - dictionary containing the Langrange and Kuhn-Tucker
multipliers on the constraints, with keys:
- C{eqnonlin} - nonlinear equality constraints
- C{ineqnonlin} - nonlinear inequality constraints
- C{mu_l} - lower (left-hand) limit on linear constraints
- C{mu_u} - upper (right-hand) limit on linear constraints
- C{lower} - lower bound on optimization variables
- C{upper} - upper bound on optimization variables
@see: U{http://www.pserc.cornell.edu/matpower/}
@author: Ray Zimmerman (PSERC Cornell)
"""
if isinstance(f_fcn, dict): ## problem dict
p = f_fcn
f_fcn = p['f_fcn']
x0 = p['x0']
if 'opt' in p: opt = p['opt']
if 'hess_fcn' in p: hess_fcn = p['hess_fcn']
if 'gh_fcn' in p: gh_fcn = p['gh_fcn']
if 'xmax' in p: xmax = p['xmax']
if 'xmin' in p: xmin = p['xmin']
if 'u' in p: u = p['u']
if 'l' in p: l = p['l']
if 'A' in p: A = p['A']
nx = x0.shape[0] # number of variables
nA = A.shape[0] if A is not None else 0 # number of original linear constr
# default argument values
if l is None or len(l) == 0: l = -Inf * ones(nA)
if u is None or len(u) == 0: u = Inf * ones(nA)
if xmin is None or len(xmin) == 0: xmin = -Inf * ones(x0.shape[0])
if xmax is None or len(xmax) == 0: xmax = Inf * ones(x0.shape[0])
if gh_fcn is None:
nonlinear = False
gn = array([])
hn = array([])
else:
nonlinear = True
if opt is None: opt = {}
# options
if "feastol" not in opt:
opt["feastol"] = 1e-06
if "gradtol" not in opt:
opt["gradtol"] = 1e-06
if "comptol" not in opt:
opt["comptol"] = 1e-06
if "costtol" not in opt:
opt["costtol"] = 1e-06
if "max_it" not in opt:
opt["max_it"] = 150
if "max_red" not in opt:
opt["max_red"] = 20
if "step_control" not in opt:
opt["step_control"] = False
if "cost_mult" not in opt:
opt["cost_mult"] = 1
if "verbose" not in opt:
opt["verbose"] = 0
# initialize history
hist = []
# constants
xi = 0.99995
sigma = 0.1
z0 = 1
alpha_min = 1e-8
rho_min = 0.95
rho_max = 1.05
mu_threshold = 1e-5
# initialize
i = 0 # iteration counter
converged = False # flag
eflag = False # exit flag
# add var limits to linear constraints
eyex = eye(nx, nx, format="csr")
AA = eyex if A is None else vstack([eyex, A], "csr")
ll = r_[xmin, l]
uu = r_[xmax, u]
# split up linear constraints
ieq = find( absolute(uu - ll) <= EPS )
igt = find( (uu >= 1e10) & (ll > -1e10) )
ilt = find( (ll <= -1e10) & (uu < 1e10) )
ibx = find( (absolute(uu - ll) > EPS) & (uu < 1e10) & (ll > -1e10) )
# zero-sized sparse matrices unsupported
Ae = AA[ieq, :] if len(ieq) else None
if len(ilt) or len(igt) or len(ibx):
idxs = [(1, ilt), (-1, igt), (1, ibx), (-1, ibx)]
Ai = vstack([sig * AA[idx, :] for sig, idx in idxs if len(idx)], 'csr')
else:
Ai = None
be = uu[ieq]
bi = r_[uu[ilt], -ll[igt], uu[ibx], -ll[ibx]]
# evaluate cost f(x0) and constraints g(x0), h(x0)
x = x0
f, df = f_fcn(x) # cost
f = f * opt["cost_mult"]
df = df * opt["cost_mult"]
if nonlinear:
hn, gn, dhn, dgn = gh_fcn(x) # nonlinear constraints
h = hn if Ai is None else r_[hn, Ai * x - bi] # inequality constraints
g = gn if Ae is None else r_[gn, Ae * x - be] # equality constraints
if (dhn is None) and (Ai is None):
dh = None
elif dhn is None:
dh = Ai.T
elif Ai is None:
dh = dhn
else:
dh = hstack([dhn, Ai.T])
if (dgn is None) and (Ae is None):
dg = None
elif dgn is None:
dg = Ae.T
elif Ae is None:
dg = dgn
else:
dg = hstack([dgn, Ae.T])
else:
h = -bi if Ai is None else Ai * x - bi # inequality constraints
g = -be if Ae is None else Ae * x - be # equality constraints
dh = None if Ai is None else Ai.T # 1st derivative of inequalities
dg = None if Ae is None else Ae.T # 1st derivative of equalities
# some dimensions
neq = g.shape[0] # number of equality constraints
niq = h.shape[0] # number of inequality constraints
neqnln = gn.shape[0] # number of nonlinear equality constraints
niqnln = hn.shape[0] # number of nonlinear inequality constraints
nlt = len(ilt) # number of upper bounded linear inequalities
ngt = len(igt) # number of lower bounded linear inequalities
nbx = len(ibx) # number of doubly bounded linear inequalities
# initialize gamma, lam, mu, z, e
gamma = 1 # barrier coefficient
lam = zeros(neq)
z = z0 * ones(niq)
mu = z0 * ones(niq)
k = find(h < -z0)
z[k] = -h[k]
k = find((gamma / z) > z0)
mu[k] = gamma / z[k]
e = ones(niq)
# check tolerance
f0 = f
if opt["step_control"]:
L = f + dot(lam, g) + dot(mu, h + z) - gamma * sum(log(z))
Lx = df.copy()
Lx = Lx + dg * lam if dg is not None else Lx
Lx = Lx + dh * mu if dh is not None else Lx
maxh = zeros(1) if len(h) == 0 else max(h)
gnorm = norm(g, Inf) if len(g) else 0.0
lam_norm = norm(lam, Inf) if len(lam) else 0.0
mu_norm = norm(mu, Inf) if len(mu) else 0.0
znorm = norm(z, Inf) if len(z) else 0.0
feascond = \
max([gnorm, maxh]) / (1 + max([norm(x, Inf), znorm]))
gradcond = \
norm(Lx, Inf) / (1 + max([lam_norm, mu_norm]))
compcond = dot(z, mu) / (1 + norm(x, Inf))
costcond = absolute(f - f0) / (1 + absolute(f0))
# save history
hist.append({'feascond': feascond, 'gradcond': gradcond,
'compcond': compcond, 'costcond': costcond, 'gamma': gamma,
'stepsize': 0, 'obj': f / opt["cost_mult"], 'alphap': 0, 'alphad': 0})
if opt["verbose"]:
s = '-sc' if opt["step_control"] else ''
v = pipsver('all')
print('Python Interior Point Solver - PIPS%s, Version %s, %s' %
(s, v['Version'], v['Date']))
if opt['verbose'] > 1:
print(" it objective step size feascond gradcond "
"compcond costcond ")
print("---- ------------ --------- ------------ ------------ "
"------------ ------------")
print("%3d %12.8g %10s %12g %12g %12g %12g" %
(i, (f / opt["cost_mult"]), "",
feascond, gradcond, compcond, costcond))
if feascond < opt["feastol"] and gradcond < opt["gradtol"] and \
compcond < opt["comptol"] and costcond < opt["costtol"]:
converged = True
if opt["verbose"]:
print("Converged!")
# do Newton iterations
while (not converged) and (i < opt["max_it"]):
# update iteration counter
i += 1
# compute update step
lmbda = {"eqnonlin": lam[range(neqnln)],
"ineqnonlin": mu[range(niqnln)]}
if nonlinear:
if hess_fcn is None:
print("pips: Hessian evaluation via finite differences "
"not yet implemented.\nPlease provide "
"your own hessian evaluation function.")
Lxx = hess_fcn(x, lmbda, opt["cost_mult"])
else:
_, _, d2f = f_fcn(x, True) # cost
Lxx = d2f * opt["cost_mult"]
rz = range(len(z))
zinvdiag = sparse((1.0 / z, (rz, rz))) if len(z) else None
rmu = range(len(mu))
mudiag = sparse((mu, (rmu, rmu))) if len(mu) else None
dh_zinv = None if dh is None else dh * zinvdiag
M = Lxx if dh is None else Lxx + dh_zinv * mudiag * dh.T
N = Lx if dh is None else Lx + dh_zinv * (mudiag * h + gamma * e)
Ab = sparse(M) if dg is None else vstack([
hstack([M, dg]),
hstack([dg.T, sparse((neq, neq))])
])
bb = r_[-N, -g]
dxdlam = spsolve(Ab.tocsr(), bb)
if any(isnan(dxdlam)):
if opt["verbose"]:
print('\nNumerically Failed\n')
eflag = -1
break
dx = dxdlam[:nx]
dlam = dxdlam[nx:nx + neq]
dz = -h - z if dh is None else -h - z - dh.T * dx
dmu = -mu if dh is None else -mu + zinvdiag * (gamma * e - mudiag * dz)
# optional step-size control
sc = False
if opt["step_control"]:
x1 = x + dx
# evaluate cost, constraints, derivatives at x1
f1, df1 = f_fcn(x1) # cost
f1 = f1 * opt["cost_mult"]
df1 = df1 * opt["cost_mult"]
if nonlinear:
hn1, gn1, dhn1, dgn1 = gh_fcn(x1) # nonlinear constraints
h1 = hn1 if Ai is None else r_[hn1, Ai * x1 - bi] # ieq constraints
g1 = gn1 if Ae is None else r_[gn1, Ae * x1 - be] # eq constraints
# 1st der of ieq
if (dhn1 is None) and (Ai is None):
dh1 = None
elif dhn1 is None:
dh1 = Ai.T
elif Ai is None:
dh1 = dhn1
else:
dh1 = hstack([dhn1, Ai.T])
# 1st der of eqs
if (dgn1 is None) and (Ae is None):
dg1 = None
elif dgn is None:
dg1 = Ae.T
elif Ae is None:
dg1 = dgn1
else:
dg1 = hstack([dgn1, Ae.T])
else:
h1 = -bi if Ai is None else Ai * x1 - bi # inequality constraints
g1 = -be if Ae is None else Ae * x1 - be # equality constraints
dh1 = dh ## 1st derivative of inequalities
dg1 = dg ## 1st derivative of equalities
# check tolerance
Lx1 = df1
Lx1 = Lx1 + dg1 * lam if dg1 is not None else Lx1
Lx1 = Lx1 + dh1 * mu if dh1 is not None else Lx1
maxh1 = zeros(1) if len(h1) == 0 else max(h1)
g1norm = norm(g1, Inf) if len(g1) else 0.0
lam1_norm = norm(lam, Inf) if len(lam) else 0.0
mu1_norm = norm(mu, Inf) if len(mu) else 0.0
z1norm = norm(z, Inf) if len(z) else 0.0
feascond1 = max([ g1norm, maxh1 ]) / \
(1 + max([ norm(x1, Inf), z1norm ]))
gradcond1 = norm(Lx1, Inf) / (1 + max([ lam1_norm, mu1_norm ]))
if (feascond1 > feascond) and (gradcond1 > gradcond):
sc = True
if sc:
alpha = 1.0
for j in range(opt["max_red"]):
dx1 = alpha * dx
x1 = x + dx1
f1, _ = f_fcn(x1) # cost
f1 = f1 * opt["cost_mult"]
if nonlinear:
hn1, gn1, _, _ = gh_fcn(x1) # nonlinear constraints
h1 = hn1 if Ai is None else r_[hn1, Ai * x1 - bi] # inequality constraints
g1 = gn1 if Ae is None else r_[gn1, Ae * x1 - be] # equality constraints
else:
h1 = -bi if Ai is None else Ai * x1 - bi # inequality constraints
g1 = -be if Ae is None else Ae * x1 - be # equality constraints
L1 = f1 + dot(lam, g1) + dot(mu, h1 + z) - gamma * sum(log(z))
if opt["verbose"] > 2:
print(" %3d %10.5f" % (-j, norm(dx1)))
rho = (L1 - L) / (dot(Lx, dx1) + 0.5 * dot(dx1, Lxx * dx1))
if (rho > rho_min) and (rho < rho_max):
break
else:
alpha = alpha / 2.0
dx = alpha * dx
dz = alpha * dz
dlam = alpha * dlam
dmu = alpha * dmu
# do the update
k = find(dz < 0.0)
alphap = min([xi * min(z[k] / -dz[k]), 1]) if len(k) else 1.0
k = find(dmu < 0.0)
alphad = min([xi * min(mu[k] / -dmu[k]), 1]) if len(k) else 1.0
x = x + alphap * dx
z = z + alphap * dz
lam = lam + alphad * dlam
mu = mu + alphad * dmu
if niq > 0:
gamma = sigma * dot(z, mu) / niq
# evaluate cost, constraints, derivatives
f, df = f_fcn(x) # cost
f = f * opt["cost_mult"]
df = df * opt["cost_mult"]
if nonlinear:
hn, gn, dhn, dgn = gh_fcn(x) # nln constraints
# g = gn if Ai is None else r_[gn, Ai * x - bi] # ieq constraints
# h = hn if Ae is None else r_[hn, Ae * x - be] # eq constraints
h = hn if Ai is None else r_[hn, Ai * x - bi] # ieq constr
g = gn if Ae is None else r_[gn, Ae * x - be] # eq constr
if (dhn is None) and (Ai is None):
dh = None
elif dhn is None:
dh = Ai.T
elif Ai is None:
dh = dhn
else:
dh = hstack([dhn, Ai.T])
if (dgn is None) and (Ae is None):
dg = None
elif dgn is None:
dg = Ae.T
elif Ae is None:
dg = dgn
else:
dg = hstack([dgn, Ae.T])
else:
h = -bi if Ai is None else Ai * x - bi # inequality constraints
g = -be if Ae is None else Ae * x - be # equality constraints
# 1st derivatives are constant, still dh = Ai.T, dg = Ae.T
Lx = df
Lx = Lx + dg * lam if dg is not None else Lx
Lx = Lx + dh * mu if dh is not None else Lx
if len(h) == 0:
maxh = zeros(1)
else:
maxh = max(h)
gnorm = norm(g, Inf) if len(g) else 0.0
lam_norm = norm(lam, Inf) if len(lam) else 0.0
mu_norm = norm(mu, Inf) if len(mu) else 0.0
znorm = norm(z, Inf) if len(z) else 0.0
feascond = \
max([gnorm, maxh]) / (1 + max([norm(x, Inf), znorm]))
gradcond = \
norm(Lx, Inf) / (1 + max([lam_norm, mu_norm]))
compcond = dot(z, mu) / (1 + norm(x, Inf))
costcond = float(absolute(f - f0) / (1 + absolute(f0)))
hist.append({'feascond': feascond, 'gradcond': gradcond,
'compcond': compcond, 'costcond': costcond, 'gamma': gamma,
'stepsize': norm(dx), 'obj': f / opt["cost_mult"],
'alphap': alphap, 'alphad': alphad})
if opt["verbose"] > 1:
print("%3d %12.8g %10.5g %12g %12g %12g %12g" %
(i, (f / opt["cost_mult"]), norm(dx), feascond, gradcond,
compcond, costcond))
if feascond < opt["feastol"] and gradcond < opt["gradtol"] and \
compcond < opt["comptol"] and costcond < opt["costtol"]:
converged = True
if opt["verbose"]:
print("Converged!")
else:
if any(isnan(x)) or (alphap < alpha_min) or \
(alphad < alpha_min) or (gamma < EPS) or (gamma > 1.0 / EPS):
if opt["verbose"]:
print("Numerically failed.")
eflag = -1
break
f0 = f
if opt["step_control"]:
L = f + dot(lam, g) + dot(mu, (h + z)) - gamma * sum(log(z))
if opt["verbose"]:
if not converged:
print("Did not converge in %d iterations." % i)
# package results
if eflag != -1:
eflag = converged
if eflag == 0:
message = 'Did not converge'
elif eflag == 1:
message = 'Converged'
elif eflag == -1:
message = 'Numerically failed'
else:
raise
output = {"iterations": i, "hist": hist, "message": message}
# zero out multipliers on non-binding constraints
mu[find( (h < -opt["feastol"]) & (mu < mu_threshold) )] = 0.0
# un-scale cost and prices
f = f / opt["cost_mult"]
lam = lam / opt["cost_mult"]
mu = mu / opt["cost_mult"]
# re-package multipliers into struct
lam_lin = lam[neqnln:neq] # lambda for linear constraints
mu_lin = mu[niqnln:niq] # mu for linear constraints
kl = find(lam_lin < 0.0) # lower bound binding
ku = find(lam_lin > 0.0) # upper bound binding
mu_l = zeros(nx + nA)
mu_l[ieq[kl]] = -lam_lin[kl]
mu_l[igt] = mu_lin[nlt:nlt + ngt]
mu_l[ibx] = mu_lin[nlt + ngt + nbx:nlt + ngt + nbx + nbx]
mu_u = zeros(nx + nA)
mu_u[ieq[ku]] = lam_lin[ku]
mu_u[ilt] = mu_lin[:nlt]
mu_u[ibx] = mu_lin[nlt + ngt:nlt + ngt + nbx]
lmbda = {'mu_l': mu_l[nx:], 'mu_u': mu_u[nx:],
'lower': mu_l[:nx], 'upper': mu_u[:nx]}
if niqnln > 0:
lmbda['ineqnonlin'] = mu[:niqnln]
if neqnln > 0:
lmbda['eqnonlin'] = lam[:neqnln]
# lmbda = {"eqnonlin": lam[:neqnln], 'ineqnonlin': mu[:niqnln],
# "mu_l": mu_l[nx:], "mu_u": mu_u[nx:],
# "lower": mu_l[:nx], "upper": mu_u[:nx]}
solution = {"x": x, "f": f, "eflag": converged,
"output": output, "lmbda": lmbda}
return solution
0
Example 19
Project: PYPOWER Source File: pipsopf_solver.py
def pipsopf_solver(om, ppopt, out_opt=None):
"""Solves AC optimal power flow using PIPS.
Inputs are an OPF model object, a PYPOWER options vector and
a dict containing keys (can be empty) for each of the desired
optional output fields.
outputs are a C{results} dict, C{success} flag and C{raw} output dict.
C{results} is a PYPOWER case dict (ppc) with the usual baseMVA, bus
branch, gen, gencost fields, along with the following additional
fields:
- C{order} see 'help ext2int' for details of this field
- C{x} final value of optimization variables (internal order)
- C{f} final objective function value
- C{mu} shadow prices on ...
- C{var}
- C{l} lower bounds on variables
- C{u} upper bounds on variables
- C{nln}
- C{l} lower bounds on nonlinear constraints
- C{u} upper bounds on nonlinear constraints
- C{lin}
- C{l} lower bounds on linear constraints
- C{u} upper bounds on linear constraints
C{success} is C{True} if solver converged successfully, C{False} otherwise
C{raw} is a raw output dict in form returned by MINOS
- xr final value of optimization variables
- pimul constraint multipliers
- info solver specific termination code
- output solver specific output information
@see: L{opf}, L{pips}
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
##----- initialization -----
## optional output
if out_opt is None:
out_opt = {}
## options
verbose = ppopt['VERBOSE']
feastol = ppopt['PDIPM_FEASTOL']
gradtol = ppopt['PDIPM_GRADTOL']
comptol = ppopt['PDIPM_COMPTOL']
costtol = ppopt['PDIPM_COSTTOL']
max_it = ppopt['PDIPM_MAX_IT']
max_red = ppopt['SCPDIPM_RED_IT']
step_control = (ppopt['OPF_ALG'] == 565) ## OPF_ALG == 565, PIPS-sc
if feastol == 0:
feastol = ppopt['OPF_VIOLATION']
opt = { 'feastol': feastol,
'gradtol': gradtol,
'comptol': comptol,
'costtol': costtol,
'max_it': max_it,
'max_red': max_red,
'step_control': step_control,
'cost_mult': 1e-4,
'verbose': verbose }
## unpack data
ppc = om.get_ppc()
baseMVA, bus, gen, branch, gencost = \
ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
vv, _, nn, _ = om.get_idx()
## problem dimensions
nb = bus.shape[0] ## number of buses
nl = branch.shape[0] ## number of branches
ny = om.getN('var', 'y') ## number of piece-wise linear costs
## linear constraints
A, l, u = om.linear_constraints()
## bounds on optimization vars
_, xmin, xmax = om.getv()
## build admittance matrices
Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)
## try to select an interior initial point
ll, uu = xmin.copy(), xmax.copy()
ll[xmin == -Inf] = -1e10 ## replace Inf with numerical proxies
uu[xmax == Inf] = 1e10
x0 = (ll + uu) / 2
Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180)
## angles set to first reference angle
x0[vv["i1"]["Va"]:vv["iN"]["Va"]] = Varefs[0]
if ny > 0:
ipwl = find(gencost[:, MODEL] == PW_LINEAR)
# PQ = r_[gen[:, PMAX], gen[:, QMAX]]
# c = totcost(gencost[ipwl, :], PQ[ipwl])
c = gencost.flatten('F')[sub2ind(gencost.shape, ipwl, NCOST+2*gencost[ipwl, NCOST])] ## largest y-value in CCV data
x0[vv["i1"]["y"]:vv["iN"]["y"]] = max(c) + 0.1 * abs(max(c))
# x0[vv["i1"]["y"]:vv["iN"]["y"]] = c + 0.1 * abs(c)
## find branches with flow limits
il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
nl2 = len(il) ## number of constrained lines
##----- run opf -----
f_fcn = lambda x, return_hessian=False: opf_costfcn(x, om, return_hessian)
gh_fcn = lambda x: opf_consfcn(x, om, Ybus, Yf[il, :], Yt[il,:], ppopt, il)
hess_fcn = lambda x, lmbda, cost_mult: opf_hessfcn(x, lmbda, om, Ybus, Yf[il, :], Yt[il, :], ppopt, il, cost_mult)
solution = pips(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt)
x, f, info, lmbda, output = solution["x"], solution["f"], \
solution["eflag"], solution["lmbda"], solution["output"]
success = (info > 0)
## update solution data
Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
Vm = x[vv["i1"]["Vm"]:vv["iN"]["Vm"]]
Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]]
Qg = x[vv["i1"]["Qg"]:vv["iN"]["Qg"]]
V = Vm * exp(1j * Va)
##----- calculate return values -----
## update voltages & generator outputs
bus[:, VA] = Va * 180 / pi
bus[:, VM] = Vm
gen[:, PG] = Pg * baseMVA
gen[:, QG] = Qg * baseMVA
gen[:, VG] = Vm[ gen[:, GEN_BUS].astype(int) ]
## 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
## line constraint is actually on square of limit
## so we must fix multipliers
muSf = zeros(nl)
muSt = zeros(nl)
if len(il) > 0:
muSf[il] = \
2 * lmbda["ineqnonlin"][:nl2] * branch[il, RATE_A] / baseMVA
muSt[il] = \
2 * lmbda["ineqnonlin"][nl2:nl2+nl2] * branch[il, RATE_A] / baseMVA
## update Lagrange multipliers
bus[:, MU_VMAX] = lmbda["upper"][vv["i1"]["Vm"]:vv["iN"]["Vm"]]
bus[:, MU_VMIN] = lmbda["lower"][vv["i1"]["Vm"]:vv["iN"]["Vm"]]
gen[:, MU_PMAX] = lmbda["upper"][vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
gen[:, MU_PMIN] = lmbda["lower"][vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
gen[:, MU_QMAX] = lmbda["upper"][vv["i1"]["Qg"]:vv["iN"]["Qg"]] / baseMVA
gen[:, MU_QMIN] = lmbda["lower"][vv["i1"]["Qg"]:vv["iN"]["Qg"]] / baseMVA
bus[:, LAM_P] = \
lmbda["eqnonlin"][nn["i1"]["Pmis"]:nn["iN"]["Pmis"]] / baseMVA
bus[:, LAM_Q] = \
lmbda["eqnonlin"][nn["i1"]["Qmis"]:nn["iN"]["Qmis"]] / baseMVA
branch[:, MU_SF] = muSf / baseMVA
branch[:, MU_ST] = muSt / baseMVA
## package up results
nlnN = om.getN('nln')
## extract multipliers for nonlinear constraints
kl = find(lmbda["eqnonlin"] < 0)
ku = find(lmbda["eqnonlin"] > 0)
nl_mu_l = zeros(nlnN)
nl_mu_u = r_[zeros(2*nb), muSf, muSt]
nl_mu_l[kl] = -lmbda["eqnonlin"][kl]
nl_mu_u[ku] = lmbda["eqnonlin"][ku]
mu = {
'var': {'l': lmbda["lower"], 'u': lmbda["upper"]},
'nln': {'l': nl_mu_l, 'u': nl_mu_u},
'lin': {'l': lmbda["mu_l"], 'u': lmbda["mu_u"]} }
results = ppc
results["bus"], results["branch"], results["gen"], \
results["om"], results["x"], results["mu"], results["f"] = \
bus, branch, gen, om, x, mu, f
pimul = r_[
results["mu"]["nln"]["l"] - results["mu"]["nln"]["u"],
results["mu"]["lin"]["l"] - results["mu"]["lin"]["u"],
-ones(ny > 0),
results["mu"]["var"]["l"] - results["mu"]["var"]["u"],
]
raw = {'xr': x, 'pimul': pimul, 'info': info, 'output': output}
return results, success, raw
0
Example 20
Project: PYPOWER Source File: polycost.py
def polycost(gencost, Pg, der=0):
"""Evaluates polynomial generator cost & derivatives.
C{f = polycost(gencost, Pg)} returns the vector of costs evaluated at C{Pg}
C{df = polycost(gencost, Pg, 1)} returns the vector of first derivatives
of costs evaluated at C{Pg}
C{d2f = polycost(gencost, Pg, 2)} returns the vector of second derivatives
of costs evaluated at C{Pg}
C{gencost} must contain only polynomial costs
C{Pg} is in MW, not p.u. (works for C{Qg} too)
@author: Ray Zimmerman (PSERC Cornell)
"""
if any(gencost[:, MODEL] == PW_LINEAR):
sys.stderr.write('polycost: all costs must be polynomial\n')
ng = len(Pg)
maxN = max( gencost[:, NCOST].astype(int) )
minN = min( gencost[:, NCOST].astype(int) )
## form coefficient matrix where 1st column is constant term, 2nd linear, etc.
c = zeros((ng, maxN))
for n in arange(minN, maxN + 1):
k = find(gencost[:, NCOST] == n) ## cost with n coefficients
c[k, :n] = gencost[k, (COST + n - 1):COST - 1:-1]
## do derivatives
for d in range(1, der + 1):
if c.shape[1] >= 2:
c = c[:, 1:maxN - d + 1]
else:
c = zeros((ng, 1))
break
for k in range(2, maxN - d + 1):
c[:, k-1] = c[:, k-1] * k
## evaluate polynomial
if len(c) == 0:
f = zeros(Pg.shape)
else:
f = c[:, :1].flatten() ## constant term
for k in range(1, c.shape[1]):
f = f + c[:, k] * Pg**k
return f
0
Example 21
Project: PYPOWER Source File: printpf.py
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)
0
Example 22
Project: PYPOWER Source File: qps_cplex.py
def qps_cplex(H, c, A, l, u, xmin, xmax, x0, opt):
"""Quadratic Program Solver based on CPLEX.
A wrapper function providing a PYPOWER standardized interface for using
C{cplexqp} or C{cplexlp} to solve the following QP (quadratic programming)
problem::
min 1/2 X'*H*x + c'*x
x
subject to::
l <= A*x <= u (linear constraints)
xmin <= x <= xmax (variable bounds)
Inputs (all optional except C{H}, C{c}, C{A} and C{l}):
- C{H} : matrix (possibly sparse) of quadratic cost coefficients
- C{c} : vector of linear cost coefficients
- C{A, l, u} : define the optional linear constraints. Default
values for the elements of L and U are -Inf and Inf, respectively.
- C{xmin, xmax} : optional lower and upper bounds on the
C{x} variables, defaults are -Inf and Inf, respectively.
- C{x0} : optional starting value of optimization vector C{x}
- C{opt} : optional options structure with the following fields,
all of which are also optional (default values shown in parentheses)
- C{verbose} (0) - controls level of progress output displayed
- 0 = no progress output
- 1 = some progress output
- 2 = verbose progress output
- C{cplex_opt} - options dict for CPLEX, value in
verbose overrides these options
- C{problem} : The inputs can alternatively be supplied in a single
C{problem} dict with fields corresponding to the input arguments
described above: C{H, c, A, l, u, xmin, xmax, x0, opt}
Outputs:
- C{x} : solution vector
- C{f} : final objective function value
- C{exitflag} : CPLEXQP/CPLEXLP exit flag
(see C{cplexqp} and C{cplexlp} docuementation for details)
- C{output} : CPLEXQP/CPLEXLP output dict
(see C{cplexqp} and C{cplexlp} docuementation for details)
- C{lmbda} : dict containing the Langrange and Kuhn-Tucker
multipliers on the constraints, with fields:
- mu_l - lower (left-hand) limit on linear constraints
- mu_u - upper (right-hand) limit on linear constraints
- lower - lower bound on optimization variables
- upper - upper bound on optimization variables
@author: Ray Zimmerman (PSERC Cornell)
"""
##----- input argument handling -----
## gather inputs
if isinstance(H, dict): ## problem struct
p = H
if 'opt' in p: opt = p['opt']
if 'x0' in p: x0 = p['x0']
if 'xmax' in p: xmax = p['xmax']
if 'xmin' in p: xmin = p['xmin']
if 'u' in p: u = p['u']
if 'l' in p: l = p['l']
if 'A' in p: A = p['A']
if 'c' in p: c = p['c']
if 'H' in p: H = p['H']
else: ## individual args
assert H is not None
assert c is not None
assert A is not None
assert l is not None
if opt is None:
opt = {}
# if x0 is None:
# x0 = array([])
# if xmax is None:
# xmax = array([])
# if xmin is None:
# xmin = array([])
## define nx, set default values for missing optional inputs
if len(H) == 0 or not any(any(H)):
if len(A) == 0 and len(xmin) == 0 and len(xmax) == 0:
stderr.write('qps_cplex: LP problem must include constraints or variable bounds\n')
else:
if len(A) > 0:
nx = shape(A)[1]
elif len(xmin) > 0:
nx = len(xmin)
else: # if len(xmax) > 0
nx = len(xmax)
else:
nx = shape(H)[0]
if len(c) == 0:
c = zeros(nx)
if len(A) > 0 and (len(l) == 0 or all(l == -Inf)) and \
(len(u) == 0 or all(u == Inf)):
A = None ## no limits => no linear constraints
nA = shape(A)[0] ## number of original linear constraints
if len(u) == 0: ## By default, linear inequalities are ...
u = Inf * ones(nA) ## ... unbounded above and ...
if len(l) == 0:
l = -Inf * ones(nA) ## ... unbounded below.
if len(xmin) == 0: ## By default, optimization variables are ...
xmin = -Inf * ones(nx) ## ... unbounded below and ...
if len(xmax) == 0:
xmax = Inf * ones(nx) ## ... unbounded above.
if len(x0) == 0:
x0 = zeros(nx)
## default options
if 'verbose' in opt:
verbose = opt['verbose']
else:
verbose = 0
#if 'max_it' in opt:
# max_it = opt['max_it']
#else:
# max_it = 0
## split up linear constraints
ieq = find( abs(u-l) <= EPS ) ## equality
igt = find( u >= 1e10 & l > -1e10 ) ## greater than, unbounded above
ilt = find( l <= -1e10 & u < 1e10 ) ## less than, unbounded below
ibx = find( (abs(u-l) > EPS) & (u < 1e10) & (l > -1e10) )
Ae = A[ieq, :]
be = u[ieq]
Ai = r_[ A[ilt, :], -A[igt, :], A[ibx, :] -A[ibx, :] ]
bi = r_[ u[ilt], -l[igt], u[ibx], -l[ibx] ]
## grab some dimensions
nlt = len(ilt) ## number of upper bounded linear inequalities
ngt = len(igt) ## number of lower bounded linear inequalities
nbx = len(ibx) ## number of doubly bounded linear inequalities
## set up options struct for CPLEX
if 'cplex_opt' in opt:
cplex_opt = cplex_options(opt['cplex_opt'])
else:
cplex_opt = cplex_options
cplex = Cplex('null')
vstr = cplex.getVersion
s, e, tE, m, t = re.compile(vstr, '(\d+\.\d+)\.')
vnum = int(t[0][0])
vrb = max([0, verbose - 1])
cplex_opt['barrier']['display'] = vrb
cplex_opt['conflict']['display'] = vrb
cplex_opt['mip']['display'] = vrb
cplex_opt['sifting']['display'] = vrb
cplex_opt['simplex']['display'] = vrb
cplex_opt['tune']['display'] = vrb
if vrb and (vnum > 12.2):
cplex_opt['diagnostics'] = 'on'
#if max_it:
# cplex_opt. ## not sure what to set here
if len(Ai) == 0 and len(Ae) == 0:
unconstrained = 1
Ae = sparse((1, nx))
be = 0
else:
unconstrained = 0
## call the solver
if verbose:
methods = [
'default',
'primal simplex',
'dual simplex',
'network simplex',
'barrier',
'sifting',
'concurrent'
]
if len(H) == 0 or not any(any(H)):
if verbose:
stdout.write('CPLEX Version %s -- %s LP solver\n' %
(vstr, methods[cplex_opt['lpmethod'] + 1]))
x, f, eflag, output, lam = \
cplexlp(c, Ai, bi, Ae, be, xmin, xmax, x0, cplex_opt)
else:
if verbose:
stdout.write('CPLEX Version %s -- %s QP solver\n' %
(vstr, methods[cplex_opt['qpmethod'] + 1]))
## ensure H is numerically symmetric
if H != H.T:
H = (H + H.T) / 2
x, f, eflag, output, lam = \
cplexqp(H, c, Ai, bi, Ae, be, xmin, xmax, x0, cplex_opt)
## check for empty results (in case optimization failed)
if len(x) == 0:
x = NaN * zeros(nx)
if len(f) == 0:
f = NaN
if len(lam) == 0:
lam['ineqlin'] = NaN * zeros(len(bi))
lam['eqlin'] = NaN * zeros(len(be))
lam['lower'] = NaN * zeros(nx)
lam['upper'] = NaN * zeros(nx)
mu_l = NaN * zeros(nA)
mu_u = NaN * zeros(nA)
else:
mu_l = zeros(nA)
mu_u = zeros(nA)
if unconstrained:
lam['eqlin'] = array([])
## negate prices depending on version
if vnum < 12.3:
lam['eqlin'] = -lam['eqlin']
lam['ineqlin'] = -lam['ineqlin']
## repackage lambdas
kl = find(lam.eqlin < 0) ## lower bound binding
ku = find(lam.eqlin > 0) ## upper bound binding
mu_l[ieq[kl]] = -lam['eqlin'][kl]
mu_l[igt] = lam['ineqlin'][nlt + arange(ngt)]
mu_l[ibx] = lam['ineqlin'][nlt + ngt + nbx + arange(nbx)]
mu_u[ieq[ku]] = lam['eqlin'][ku]
mu_u[ilt] = lam['ineqlin'][:nlt]
mu_u[ibx] = lam['ineqlin'][nlt + ngt + arange(nbx)]
lmbda = {
'mu_l': mu_l,
'mu_u': mu_u,
'lower': lam.lower,
'upper': lam.upper
}
return x, f, eflag, output, lmbda
0
Example 23
Project: PYPOWER Source File: qps_gurobi.py
def qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt):
"""Quadratic Program Solver based on GUROBI.
A wrapper function providing a PYPOWER standardized interface for using
gurobipy to solve the following QP (quadratic programming)
problem:
min 1/2 x'*H*x + c'*x
x
subject to
l <= A*x <= u (linear constraints)
xmin <= x <= xmax (variable bounds)
Inputs (all optional except H, c, A and l):
H : matrix (possibly sparse) of quadratic cost coefficients
c : vector of linear cost coefficients
A, l, u : define the optional linear constraints. Default
values for the elements of l and u are -Inf and Inf,
respectively.
xmin, xmax : optional lower and upper bounds on the
C{x} variables, defaults are -Inf and Inf, respectively.
x0 : optional starting value of optimization vector C{x}
opt : optional options structure with the following fields,
all of which are also optional (default values shown in
parentheses)
verbose (0) - controls level of progress output displayed
0 = no progress output
1 = some progress output
2 = verbose progress output
grb_opt - options dict for Gurobi, value in
verbose overrides these options
problem : The inputs can alternatively be supplied in a single
PROBLEM dict with fields corresponding to the input arguments
described above: H, c, A, l, u, xmin, xmax, x0, opt
Outputs:
x : solution vector
f : final objective function value
exitflag : gurobipy exit flag
1 = converged
0 or negative values = negative of GUROBI_MEX exit flag
(see gurobipy docuementation for details)
output : gurobipy output dict
(see gurobipy docuementation for details)
lmbda : dict containing the Langrange and Kuhn-Tucker
multipliers on the constraints, with fields:
mu_l - lower (left-hand) limit on linear constraints
mu_u - upper (right-hand) limit on linear constraints
lower - lower bound on optimization variables
upper - upper bound on optimization variables
Note the calling syntax is almost identical to that of QUADPROG
from MathWorks' Optimization Toolbox. The main difference is that
the linear constraints are specified with A, l, u instead of
A, b, Aeq, beq.
Calling syntax options:
x, f, exitflag, output, lmbda = ...
qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt)
r = qps_gurobi(H, c, A, l, u)
r = qps_gurobi(H, c, A, l, u, xmin, xmax)
r = qps_gurobi(H, c, A, l, u, xmin, xmax, x0)
r = qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt)
r = qps_gurobi(problem), where problem is a dict with fields:
H, c, A, l, u, xmin, xmax, x0, opt
all fields except 'c', 'A' and 'l' or 'u' are optional
Example: (problem from from http://www.jmu.edu/docs/sasdoc/sashtml/iml/chap8/sect12.htm)
H = [ 1003.1 4.3 6.3 5.9;
4.3 2.2 2.1 3.9;
6.3 2.1 3.5 4.8;
5.9 3.9 4.8 10 ]
c = zeros((4, 1))
A = [ [1 1 1 1]
[0.17 0.11 0.10 0.18] ]
l = [1; 0.10]
u = [1; Inf]
xmin = zeros((4, 1))
x0 = [1; 0; 0; 1]
opt = {'verbose': 2}
x, f, s, out, lmbda = qps_gurobi(H, c, A, l, u, xmin, [], x0, opt)
@see: L{gurobipy}.
"""
import gurobipy
##----- input argument handling -----
## gather inputs
if isinstance(H, dict): ## problem struct
p = H
if 'opt' in p: opt = p['opt']
if 'x0' in p: x0 = p['x0']
if 'xmax' in p: xmax = p['xmax']
if 'xmin' in p: xmin = p['xmin']
if 'u' in p: u = p['u']
if 'l' in p: l = p['l']
if 'A' in p: A = p['A']
if 'c' in p: c = p['c']
if 'H' in p: H = p['H']
else: ## individual args
assert H is not None
assert c is not None
assert A is not None
assert l is not None
if opt is None:
opt = {}
# if x0 is None:
# x0 = array([])
# if xmax is None:
# xmax = array([])
# if xmin is None:
# xmin = array([])
## define nx, set default values for missing optional inputs
if len(H) == 0 or not any(any(H)):
if len(A) == 0 and len(xmin) == 0 and len(xmax) == 0:
stderr.write('qps_gurobi: LP problem must include constraints or variable bounds\n')
else:
if len(A) > 0:
nx = shape(A)[1]
elif len(xmin) > 0:
nx = len(xmin)
else: # if len(xmax) > 0
nx = len(xmax)
H = sparse((nx, nx))
else:
nx = shape(H)[0]
if len(c) == 0:
c = zeros(nx)
if len(A) > 0 and (len(l) == 0 or all(l == -Inf)) and \
(len(u) == 0 or all(u == Inf)):
A = None ## no limits => no linear constraints
nA = shape(A)[0] ## number of original linear constraints
if nA:
if len(u) == 0: ## By default, linear inequalities are ...
u = Inf * ones(nA) ## ... unbounded above and ...
if len(l) == 0:
l = -Inf * ones(nA) ## ... unbounded below.
if len(x0) == 0:
x0 = zeros(nx)
## default options
if 'verbose' in opt:
verbose = opt['verbose']
else:
verbose = 0
# if 'max_it' in opt:
# max_it = opt['max_it']
# else:
# max_it = 0
## set up options struct for Gurobi
if 'grb_opt' in opt:
g_opt = gurobi_options(opt['grb_opt'])
else:
g_opt = gurobi_options()
g_opt['Display'] = min(verbose, 3)
if verbose:
g_opt['DisplayInterval'] = 1
else:
g_opt['DisplayInterval'] = Inf
if not issparse(A):
A = sparse(A)
## split up linear constraints
ieq = find( abs(u-l) <= EPS ) ## equality
igt = find( u >= 1e10 & l > -1e10 ) ## greater than, unbounded above
ilt = find( l <= -1e10 & u < 1e10 ) ## less than, unbounded below
ibx = find( (abs(u-l) > EPS) & (u < 1e10) & (l > -1e10) )
## grab some dimensions
nlt = len(ilt) ## number of upper bounded linear inequalities
ngt = len(igt) ## number of lower bounded linear inequalities
nbx = len(ibx) ## number of doubly bounded linear inequalities
neq = len(ieq) ## number of equalities
niq = nlt + ngt + 2 * nbx ## number of inequalities
AA = [ A[ieq, :], A[ilt, :], -A[igt, :], A[ibx, :], -A[ibx, :] ]
bb = [ u[ieq], u[ilt], -l[igt], u[ibx], -l[ibx] ]
contypes = '=' * neq + '<' * niq
## call the solver
if len(H) == 0 or not any(any(H)):
lpqp = 'LP'
else:
lpqp = 'QP'
rr, cc, vv = find(H)
g_opt['QP']['qrow'] = int(rr.T - 1)
g_opt['QP']['qcol'] = int(cc.T - 1)
g_opt['QP']['qval'] = 0.5 * vv.T
if verbose:
methods = [
'primal simplex',
'dual simplex',
'interior point',
'concurrent',
'deterministic concurrent'
]
print('Gurobi Version %s -- %s %s solver\n'
'<unknown>' % (methods[g_opt['Method'] + 1], lpqp))
x, f, eflag, output, lmbda = \
gurobipy(c.T, 1, AA, bb, contypes, xmin, xmax, 'C', g_opt)
pi = lmbda['Pi']
rc = lmbda['RC']
output['flag'] = eflag
if eflag == 2:
eflag = 1 ## optimal solution found
else:
eflag = -eflag ## failed somehow
## check for empty results (in case optimization failed)
lam = {}
if len(x) == 0:
x = NaN(nx, 1);
lam['lower'] = NaN(nx)
lam['upper'] = NaN(nx)
else:
lam['lower'] = zeros(nx)
lam['upper'] = zeros(nx)
if len(f) == 0:
f = NaN
if len(pi) == 0:
pi = NaN(len(bb))
kl = find(rc > 0); ## lower bound binding
ku = find(rc < 0); ## upper bound binding
lam['lower'][kl] = rc[kl]
lam['upper'][ku] = -rc[ku]
lam['eqlin'] = pi[:neq + 1]
lam['ineqlin'] = pi[neq + range(niq + 1)]
mu_l = zeros(nA)
mu_u = zeros(nA)
## repackage lmbdas
kl = find(lam['eqlin'] > 0) ## lower bound binding
ku = find(lam['eqlin'] < 0) ## upper bound binding
mu_l[ieq[kl]] = lam['eqlin'][kl]
mu_l[igt] = -lam['ineqlin'][nlt + range(ngt + 1)]
mu_l[ibx] = -lam['ineqlin'][nlt + ngt + nbx + range(nbx)]
mu_u[ieq[ku]] = -lam['eqlin'][ku]
mu_u[ilt] = -lam['ineqlin'][:nlt + 1]
mu_u[ibx] = -lam['ineqlin'][nlt + ngt + range(nbx + 1)]
lmbda = {
'mu_l': mu_l,
'mu_u': mu_u,
'lower': lam['lower'],
'upper': lam['upper']
}
return x, f, eflag, output, lmbda
0
Example 24
Project: PYPOWER Source File: qps_ipopt.py
def qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt):
"""Quadratic Program Solver based on IPOPT.
Uses IPOPT to solve the following QP (quadratic programming) problem::
min 1/2 x'*H*x + c'*x
x
subject to::
l <= A*x <= u (linear constraints)
xmin <= x <= xmax (variable bounds)
Inputs (all optional except C{H}, C{C}, C{A} and C{L}):
- C{H} : matrix (possibly sparse) of quadratic cost coefficients
- C{C} : vector of linear cost coefficients
- C{A, l, u} : define the optional linear constraints. Default
values for the elements of C{l} and C{u} are -Inf and Inf,
respectively.
- C{xmin, xmax} : optional lower and upper bounds on the
C{x} variables, defaults are -Inf and Inf, respectively.
- C{x0} : optional starting value of optimization vector C{x}
- C{opt} : optional options structure with the following fields,
all of which are also optional (default values shown in parentheses)
- C{verbose} (0) - controls level of progress output displayed
- 0 = no progress output
- 1 = some progress output
- 2 = verbose progress output
- C{max_it} (0) - maximum number of iterations allowed
- 0 = use algorithm default
- C{ipopt_opt} - options struct for IPOPT, values in
C{verbose} and C{max_it} override these options
- C{problem} : The inputs can alternatively be supplied in a single
C{problem} dict with fields corresponding to the input arguments
described above: C{H, c, A, l, u, xmin, xmax, x0, opt}
Outputs:
- C{x} : solution vector
- C{f} : final objective function value
- C{exitflag} : exit flag
- 1 = first order optimality conditions satisfied
- 0 = maximum number of iterations reached
- -1 = numerically failed
- C{output} : output struct with the following fields:
- C{iterations} - number of iterations performed
- C{hist} - dict list with trajectories of the following:
C{feascond}, C{gradcond}, C{compcond}, C{costcond}, C{gamma},
C{stepsize}, C{obj}, C{alphap}, C{alphad}
- message - exit message
- C{lmbda} : dict containing the Langrange and Kuhn-Tucker
multipliers on the constraints, with fields:
- C{mu_l} - lower (left-hand) limit on linear constraints
- C{mu_u} - upper (right-hand) limit on linear constraints
- C{lower} - lower bound on optimization variables
- C{upper} - upper bound on optimization variables
Calling syntax options::
x, f, exitflag, output, lmbda = \
qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt)
x = qps_ipopt(H, c, A, l, u)
x = qps_ipopt(H, c, A, l, u, xmin, xmax)
x = qps_ipopt(H, c, A, l, u, xmin, xmax, x0)
x = qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt)
x = qps_ipopt(problem), where problem is a struct with fields:
H, c, A, l, u, xmin, xmax, x0, opt
all fields except 'c', 'A' and 'l' or 'u' are optional
x = qps_ipopt(...)
x, f = qps_ipopt(...)
x, f, exitflag = qps_ipopt(...)
x, f, exitflag, output = qps_ipopt(...)
x, f, exitflag, output, lmbda = qps_ipopt(...)
Example::
H = [ 1003.1 4.3 6.3 5.9;
4.3 2.2 2.1 3.9;
6.3 2.1 3.5 4.8;
5.9 3.9 4.8 10 ]
c = zeros((4, 1))
A = [ 1 1 1 1
0.17 0.11 0.10 0.18 ]
l = [1, 0.10]
u = [1, Inf]
xmin = zeros((4, 1))
x0 = [1, 0, 0, 1]
opt = {'verbose': 2)
x, f, s, out, lambda = qps_ipopt(H, c, A, l, u, xmin, [], x0, opt)
Problem from U{http://www.jmu.edu/docs/sasdoc/sashtml/iml/chap8/sect12.htm}
@see: C{pyipopt}, L{ipopt_options}
@author: Ray Zimmerman (PSERC Cornell)
"""
##----- input argument handling -----
## gather inputs
if isinstance(H, dict): ## problem struct
p = H
if 'opt' in p: opt = p['opt']
if 'x0' in p: x0 = p['x0']
if 'xmax' in p: xmax = p['xmax']
if 'xmin' in p: xmin = p['xmin']
if 'u' in p: u = p['u']
if 'l' in p: l = p['l']
if 'A' in p: A = p['A']
if 'c' in p: c = p['c']
if 'H' in p: H = p['H']
else: ## individual args
assert H is not None
assert c is not None
assert A is not None
assert l is not None
if opt is None:
opt = {}
# if x0 is None:
# x0 = array([])
# if xmax is None:
# xmax = array([])
# if xmin is None:
# xmin = array([])
## define nx, set default values for missing optional inputs
if len(H) == 0 or not any(any(H)):
if len(A) == 0 and len(xmin) == 0 and len(xmax) == 0:
stderr.write('qps_ipopt: LP problem must include constraints or variable bounds\n')
else:
if len(A) > 0:
nx = shape(A)[1]
elif len(xmin) > 0:
nx = len(xmin)
else: # if len(xmax) > 0
nx = len(xmax)
H = sparse((nx, nx))
else:
nx = shape(H)[0]
if len(c) == 0:
c = zeros(nx)
if len(A) > 0 and (len(l) == 0 or all(l == -Inf)) and \
(len(u) == 0 or all(u == Inf)):
A = None ## no limits => no linear constraints
nA = shape(A)[0] ## number of original linear constraints
if nA:
if len(u) == 0: ## By default, linear inequalities are ...
u = Inf * ones(nA) ## ... unbounded above and ...
if len(l) == 0:
l = -Inf * ones(nA) ## ... unbounded below.
if len(x0) == 0:
x0 = zeros(nx)
## default options
if 'verbose' in opt:
verbose = opt['verbose']
else:
verbose = 0
if 'max_it' in opt:
max_it = opt['max_it']
else:
max_it = 0
## make sure args are sparse/full as expected by IPOPT
if len(H) > 0:
if not issparse(H):
H = sparse(H)
if not issparse(A):
A = sparse(A)
##----- run optimization -----
## set options dict for IPOPT
options = {}
if 'ipopt_opt' in opt:
options['ipopt'] = ipopt_options(opt['ipopt_opt'])
else:
options['ipopt'] = ipopt_options()
options['ipopt']['jac_c_constant'] = 'yes'
options['ipopt']['jac_d_constant'] = 'yes'
options['ipopt']['hessian_constant'] = 'yes'
options['ipopt']['least_square_init_primal'] = 'yes'
options['ipopt']['least_square_init_duals'] = 'yes'
# options['ipopt']['mehrotra_algorithm'] = 'yes' ## default 'no'
if verbose:
options['ipopt']['print_level'] = min(12, verbose * 2 + 1)
else:
options['ipopt']['print_level = 0']
if max_it:
options['ipopt']['max_iter'] = max_it
## define variable and constraint bounds, if given
if nA:
options['cu'] = u
options['cl'] = l
if len(xmin) > 0:
options['lb'] = xmin
if len(xmax) > 0:
options['ub'] = xmax
## assign function handles
funcs = {}
funcs['objective'] = lambda x: 0.5 * x.T * H * x + c.T * x
funcs['gradient'] = lambda x: H * x + c
funcs['constraints'] = lambda x: A * x
funcs['jacobian'] = lambda x: A
funcs['jacobianstructure'] = lambda : A
funcs['hessian'] = lambda x, sigma, lmbda: tril(H)
funcs['hessianstructure'] = lambda : tril(H)
## run the optimization
x, info = pyipopt(x0, funcs, options)
if info['status'] == 0 | info['status'] == 1:
eflag = 1
else:
eflag = 0
output = {}
if 'iter' in info:
output['iterations'] = info['iter']
output['info'] = info['status']
f = funcs['objective'](x)
## repackage lmbdas
kl = find(info['lmbda'] < 0) ## lower bound binding
ku = find(info['lmbda'] > 0) ## upper bound binding
mu_l = zeros(nA)
mu_l[kl] = -info['lmbda'][kl]
mu_u = zeros(nA)
mu_u[ku] = info['lmbda'][ku]
lmbda = {
'mu_l': mu_l,
'mu_u': mu_u,
'lower': info['zl'],
'upper': info['zu']
}
return x, f, eflag, output, lmbda
0
Example 25
Project: PYPOWER Source File: qps_mosek.py
def qps_mosek(H, c=None, A=None, l=None, u=None, xmin=None, xmax=None,
x0=None, opt=None):
"""Quadratic Program Solver based on MOSEK.
A wrapper function providing a PYPOWER standardized interface for using
MOSEKOPT to solve the following QP (quadratic programming) problem::
min 1/2 x'*H*x + c'*x
x
subject to::
l <= A*x <= u (linear constraints)
xmin <= x <= xmax (variable bounds)
Inputs (all optional except C{H}, C{C}, C{A} and C{L}):
- C{H} : matrix (possibly sparse) of quadratic cost coefficients
- C{C} : vector of linear cost coefficients
- C{A, l, u} : define the optional linear constraints. Default
values for the elements of L and U are -Inf and Inf, respectively.
- xmin, xmax : optional lower and upper bounds on the
C{x} variables, defaults are -Inf and Inf, respectively.
- C{x0} : optional starting value of optimization vector C{x}
- C{opt} : optional options structure with the following fields,
all of which are also optional (default values shown in parentheses)
- C{verbose} (0) - controls level of progress output displayed
- 0 = no progress output
- 1 = some progress output
- 2 = verbose progress output
- C{max_it} (0) - maximum number of iterations allowed
- 0 = use algorithm default
- C{mosek_opt} - options struct for MOSEK, values in
C{verbose} and C{max_it} override these options
- C{problem} : The inputs can alternatively be supplied in a single
C{problem} struct with fields corresponding to the input arguments
described above: C{H, c, A, l, u, xmin, xmax, x0, opt}
Outputs:
- C{x} : solution vector
- C{f} : final objective function value
- C{exitflag} : exit flag
- 1 = success
- 0 = terminated at maximum number of iterations
- -1 = primal or dual infeasible
< 0 = the negative of the MOSEK return code
- C{output} : output dict with the following fields:
- C{r} - MOSEK return code
- C{res} - MOSEK result dict
- C{lmbda} : dict containing the Langrange and Kuhn-Tucker
multipliers on the constraints, with fields:
- C{mu_l} - lower (left-hand) limit on linear constraints
- C{mu_u} - upper (right-hand) limit on linear constraints
- C{lower} - lower bound on optimization variables
- C{upper} - upper bound on optimization variables
@author: Ray Zimmerman (PSERC Cornell)
"""
##----- input argument handling -----
## gather inputs
if isinstance(H, dict): ## problem struct
p = H
else: ## individual args
p = {'H': H, 'c': c, 'A': A, 'l': l, 'u': u}
if xmin is not None:
p['xmin'] = xmin
if xmax is not None:
p['xmax'] = xmax
if x0 is not None:
p['x0'] = x0
if opt is not None:
p['opt'] = opt
## define nx, set default values for H and c
if 'H' not in p or len(p['H']) or not any(any(p['H'])):
if ('A' not in p) | len(p['A']) == 0 & \
('xmin' not in p) | len(p['xmin']) == 0 & \
('xmax' not in p) | len(p['xmax']) == 0:
stderr.write('qps_mosek: LP problem must include constraints or variable bounds\n')
else:
if 'A' in p & len(p['A']) > 0:
nx = shape(p['A'])[1]
elif 'xmin' in p & len(p['xmin']) > 0:
nx = len(p['xmin'])
else: # if isfield(p, 'xmax') && ~isempty(p.xmax)
nx = len(p['xmax'])
p['H'] = sparse((nx, nx))
qp = 0
else:
nx = shape(p['H'])[0]
qp = 1
if 'c' not in p | len(p['c']) == 0:
p['c'] = zeros(nx)
if 'x0' not in p | len(p['x0']) == 0:
p['x0'] = zeros(nx)
## default options
if 'opt' not in p:
p['opt'] = []
if 'verbose' in p['opt']:
verbose = p['opt']['verbose']
else:
verbose = 0
if 'max_it' in p['opt']:
max_it = p['opt']['max_it']
else:
max_it = 0
if 'mosek_opt' in p['opt']:
mosek_opt = mosek_options(p['opt']['mosek_opt'])
else:
mosek_opt = mosek_options()
if max_it:
mosek_opt['MSK_IPAR_INTPNT_MAX_ITERATIONS'] = max_it
if qp:
mosek_opt['MSK_IPAR_OPTIMIZER'] = 0 ## default solver only for QP
## set up problem struct for MOSEK
prob = {}
prob['c'] = p['c']
if qp:
prob['qosubi'], prob['qosubj'], prob['qoval'] = find(tril(sparse(p['H'])))
if 'A' in p & len(p['A']) > 0:
prob['a'] = sparse(p['A'])
if 'l' in p & len(p['A']) > 0:
prob['blc'] = p['l']
if 'u' in p & len(p['A']) > 0:
prob['buc'] = p['u']
if 'xmin' in p & len(p['xmin']) > 0:
prob['blx'] = p['xmin']
if 'xmax' in p & len(p['xmax']) > 0:
prob['bux'] = p['xmax']
## A is not allowed to be empty
if 'a' not in prob | len(prob['a']) == 0:
unconstrained = True
prob['a'] = sparse((1, (1, 1)), (1, nx))
prob.blc = -Inf
prob.buc = Inf
else:
unconstrained = False
##----- run optimization -----
if verbose:
methods = [
'default',
'interior point',
'<default>',
'<default>',
'primal simplex',
'dual simplex',
'primal dual simplex',
'automatic simplex',
'<default>',
'<default>',
'concurrent'
]
if len(H) == 0 or not any(any(H)):
lpqp = 'LP'
else:
lpqp = 'QP'
# (this code is also in mpver.m)
# MOSEK Version 6.0.0.93 (Build date: 2010-10-26 13:03:27)
# MOSEK Version 6.0.0.106 (Build date: 2011-3-17 10:46:54)
# pat = 'Version (\.*\d)+.*Build date: (\d\d\d\d-\d\d-\d\d)';
pat = 'Version (\.*\d)+.*Build date: (\d+-\d+-\d+)'
s, e, tE, m, t = re.compile(eval('mosekopt'), pat)
if len(t) == 0:
vn = '<unknown>'
else:
vn = t[0][0]
print('MOSEK Version %s -- %s %s solver\n' %
(vn, methods[mosek_opt['MSK_IPAR_OPTIMIZER'] + 1], lpqp))
cmd = 'minimize echo(%d)' % verbose
r, res = mosekopt(cmd, prob, mosek_opt)
##----- repackage results -----
if 'sol' in res:
if 'bas' in res['sol']:
sol = res['sol.bas']
else:
sol = res['sol.itr']
x = sol['xx']
else:
sol = array([])
x = array([])
##----- process return codes -----
if 'symbcon' in res:
sc = res['symbcon']
else:
r2, res2 = mosekopt('symbcon echo(0)')
sc = res2['symbcon']
eflag = -r
msg = ''
if r == sc.MSK_RES_OK:
if len(sol) > 0:
# if sol['solsta'] == sc.MSK_SOL_STA_OPTIMAL:
if sol['solsta'] == 'OPTIMAL':
msg = 'The solution is optimal.'
eflag = 1
else:
eflag = -1
# if sol['prosta'] == sc['MSK_PRO_STA_PRIM_INFEAS']:
if sol['prosta'] == 'PRIMAL_INFEASIBLE':
msg = 'The problem is primal infeasible.'
# elif sol['prosta'] == sc['MSK_PRO_STA_DUAL_INFEAS']:
elif sol['prosta'] == 'DUAL_INFEASIBLE':
msg = 'The problem is dual infeasible.'
else:
msg = sol['solsta']
elif r == sc['MSK_RES_TRM_MAX_ITERATIONS']:
eflag = 0
msg = 'The optimizer terminated at the maximum number of iterations.'
else:
if 'rmsg' in res and 'rcodestr' in res:
msg = '%s : %s' % (res['rcodestr'], res['rmsg'])
else:
msg = 'MOSEK return code = %d' % r
## always alert user if license is expired
if (verbose or r == 1001) and len(msg) < 0:
stdout.write('%s\n' % msg)
##----- repackage results -----
if r == 0:
f = p['c'].T * x
if len(p['H']) > 0:
f = 0.5 * x.T * p['H'] * x + f
else:
f = array([])
output = {}
output['r'] = r
output['res'] = res
if 'sol' in res:
lmbda = {}
lmbda['lower'] = sol['slx']
lmbda['upper'] = sol['sux']
lmbda['mu_l'] = sol['slc']
lmbda['mu_u'] = sol['suc']
if unconstrained:
lmbda['mu_l'] = array([])
lmbda['mu_u'] = array([])
else:
lmbda = array([])
return x, f, eflag, output, lmbda
0
Example 26
Project: PYPOWER Source File: runpf.py
def runpf(casedata=None, ppopt=None, fname='', solvedcase=''):
"""Runs a power flow.
Runs a power flow [full AC Newton's method by default] and optionally
returns the solved values in the data matrices, a flag which is C{True} if
the algorithm was successful in finding a solution, and the elapsed
time in seconds. All input arguments are optional. If C{casename} is
provided it specifies the name of the input data file or dict
containing the power flow data. The default value is 'case9'.
If the ppopt is provided it overrides the default PYPOWER options
vector and can be used to specify the solution algorithm and output
options among other things. If the 3rd argument is given the pretty
printed output will be appended to the file whose name is given in
C{fname}. If C{solvedcase} is specified the solved case will be written
to a case file in PYPOWER format with the specified name. If C{solvedcase}
ends with '.mat' it saves the case as a MAT-file otherwise it saves it
as a Python-file.
If the C{ENFORCE_Q_LIMS} options is set to C{True} [default is false] then
if any generator reactive power limit is violated after running the AC
power flow, the corresponding bus is converted to a PQ bus, with Qg at
the limit, and the case is re-run. The voltage magnitude at the bus
will deviate from the specified value in order to satisfy the reactive
power limit. If the reference bus is converted to PQ, the first
remaining PV bus will be used as the slack bus for the next iteration.
This may result in the real power output at this generator being
slightly off from the specified values.
Enforcing of generator Q limits inspired by contributions from Mu Lin,
Lincoln University, New Zealand (1/14/05).
@author: Ray Zimmerman (PSERC Cornell)
"""
## default arguments
if casedata is None:
casedata = join(dirname(__file__), 'case9')
ppopt = ppoption(ppopt)
## options
verbose = ppopt["VERBOSE"]
qlim = ppopt["ENFORCE_Q_LIMS"] ## enforce Q limits on gens?
dc = ppopt["PF_DC"] ## use DC formulation?
## read data
ppc = loadcase(casedata)
## add zero columns to branch for flows if needed
if ppc["branch"].shape[1] < QT:
ppc["branch"] = c_[ppc["branch"],
zeros((ppc["branch"].shape[0],
QT - ppc["branch"].shape[1] + 1))]
## convert to internal indexing
ppc = ext2int(ppc)
baseMVA, bus, gen, branch = \
ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"]
## get bus index lists of each type of bus
ref, pv, pq = bustypes(bus, gen)
## generator info
on = find(gen[:, GEN_STATUS] > 0) ## which generators are on?
gbus = gen[on, GEN_BUS].astype(int) ## what buses are they at?
##----- run the power flow -----
t0 = time()
if verbose > 0:
v = ppver('all')
stdout.write('PYPOWER Version %s, %s' % (v["Version"], v["Date"]))
if dc: # DC formulation
if verbose:
stdout.write(' -- DC Power Flow\n')
## initial state
Va0 = bus[:, VA] * (pi / 180)
## build B matrices and phase shift injections
B, Bf, Pbusinj, Pfinj = makeBdc(baseMVA, bus, branch)
## compute complex bus power injections [generation - load]
## adjusted for phase shifters and real shunts
Pbus = makeSbus(baseMVA, bus, gen).real - Pbusinj - bus[:, GS] / baseMVA
## "run" the power flow
Va = dcpf(B, Pbus, Va0, ref, pv, pq)
## update data matrices with solution
branch[:, [QF, QT]] = zeros((branch.shape[0], 2))
branch[:, PF] = (Bf * Va + Pfinj) * baseMVA
branch[:, PT] = -branch[:, PF]
bus[:, VM] = ones(bus.shape[0])
bus[:, VA] = Va * (180 / pi)
## update Pg for slack generator (1st gen at ref bus)
## (note: other gens at ref bus are accounted for in Pbus)
## Pg = Pinj + Pload + Gs
## newPg = oldPg + newPinj - oldPinj
refgen = zeros(len(ref), dtype=int)
for k in range(len(ref)):
temp = find(gbus == ref[k])
refgen[k] = on[temp[0]]
gen[refgen, PG] = gen[refgen, PG] + (B[ref, :] * Va - Pbus[ref]) * baseMVA
success = 1
else: ## AC formulation
alg = ppopt['PF_ALG']
if verbose > 0:
if alg == 1:
solver = 'Newton'
elif alg == 2:
solver = 'fast-decoupled, XB'
elif alg == 3:
solver = 'fast-decoupled, BX'
elif alg == 4:
solver = 'Gauss-Seidel'
else:
solver = 'unknown'
print(' -- AC Power Flow (%s)\n' % solver)
## initial state
# V0 = ones(bus.shape[0]) ## flat start
V0 = bus[:, VM] * exp(1j * pi/180 * bus[:, VA])
V0[gbus] = gen[on, VG] / abs(V0[gbus]) * V0[gbus]
if qlim:
ref0 = ref ## save index and angle of
Varef0 = bus[ref0, VA] ## original reference bus(es)
limited = [] ## list of indices of gens @ Q lims
fixedQg = zeros(gen.shape[0]) ## Qg of gens at Q limits
repeat = True
while repeat:
## build admittance matrices
Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)
## compute complex bus power injections [generation - load]
Sbus = makeSbus(baseMVA, bus, gen)
## run the power flow
alg = ppopt["PF_ALG"]
if alg == 1:
V, success, _ = newtonpf(Ybus, Sbus, V0, ref, pv, pq, ppopt)
elif alg == 2 or alg == 3:
Bp, Bpp = makeB(baseMVA, bus, branch, alg)
V, success, _ = fdpf(Ybus, Sbus, V0, Bp, Bpp, ref, pv, pq, ppopt)
elif alg == 4:
V, success, _ = gausspf(Ybus, Sbus, V0, ref, pv, pq, ppopt)
else:
stderr.write('Only Newton''s method, fast-decoupled, and '
'Gauss-Seidel power flow algorithms currently '
'implemented.\n')
## update data matrices with solution
bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref, pv, pq)
if qlim: ## enforce generator Q limits
## find gens with violated Q constraints
gen_status = gen[:, GEN_STATUS] > 0
qg_max_lim = gen[:, QG] > gen[:, QMAX]
qg_min_lim = gen[:, QG] < gen[:, QMIN]
mx = find( gen_status & qg_max_lim )
mn = find( gen_status & qg_min_lim )
if len(mx) > 0 or len(mn) > 0: ## we have some Q limit violations
# No PV generators
if len(pv) == 0:
if verbose:
if len(mx) > 0:
print('Gen %d [only one left] exceeds upper Q limit : INFEASIBLE PROBLEM\n' % mx + 1)
else:
print('Gen %d [only one left] exceeds lower Q limit : INFEASIBLE PROBLEM\n' % mn + 1)
success = 0
break
## one at a time?
if qlim == 2: ## fix largest violation, ignore the rest
k = argmax(r_[gen[mx, QG] - gen[mx, QMAX],
gen[mn, QMIN] - gen[mn, QG]])
if k > len(mx):
mn = mn[k - len(mx)]
mx = []
else:
mx = mx[k]
mn = []
if verbose and len(mx) > 0:
for i in range(len(mx)):
print('Gen ' + str(mx[i] + 1) + ' at upper Q limit, converting to PQ bus\n')
if verbose and len(mn) > 0:
for i in range(len(mn)):
print('Gen ' + str(mn[i] + 1) + ' at lower Q limit, converting to PQ bus\n')
## save corresponding limit values
fixedQg[mx] = gen[mx, QMAX]
fixedQg[mn] = gen[mn, QMIN]
mx = r_[mx, mn].astype(int)
## convert to PQ bus
gen[mx, QG] = fixedQg[mx] ## set Qg to binding
for i in range(len(mx)): ## [one at a time, since they may be at same bus]
gen[mx[i], GEN_STATUS] = 0 ## temporarily turn off gen,
bi = gen[mx[i], GEN_BUS] ## adjust load accordingly,
bus[bi, [PD, QD]] = (bus[bi, [PD, QD]] - gen[mx[i], [PG, QG]])
if len(ref) > 1 and any(bus[gen[mx, GEN_BUS], BUS_TYPE] == REF):
raise ValueError('Sorry, PYPOWER cannot enforce Q '
'limits for slack buses in systems '
'with multiple slacks.')
bus[gen[mx, GEN_BUS].astype(int), BUS_TYPE] = PQ ## & set bus type to PQ
## update bus index lists of each type of bus
ref_temp = ref
ref, pv, pq = bustypes(bus, gen)
if verbose and ref != ref_temp:
print('Bus %d is new slack bus\n' % ref)
limited = r_[limited, mx].astype(int)
else:
repeat = 0 ## no more generator Q limits violated
else:
repeat = 0 ## don't enforce generator Q limits, once is enough
if qlim and len(limited) > 0:
## restore injections from limited gens [those at Q limits]
gen[limited, QG] = fixedQg[limited] ## restore Qg value,
for i in range(len(limited)): ## [one at a time, since they may be at same bus]
bi = gen[limited[i], GEN_BUS] ## re-adjust load,
bus[bi, [PD, QD]] = bus[bi, [PD, QD]] + gen[limited[i], [PG, QG]]
gen[limited[i], GEN_STATUS] = 1 ## and turn gen back on
if ref != ref0:
## adjust voltage angles to make original ref bus correct
bus[:, VA] = bus[:, VA] - bus[ref0, VA] + Varef0
ppc["et"] = time() - t0
ppc["success"] = success
##----- output results -----
## convert back to original bus numbering & print results
ppc["bus"], ppc["gen"], ppc["branch"] = bus, gen, branch
results = int2ext(ppc)
## zero out result fields of out-of-service gens & branches
if len(results["order"]["gen"]["status"]["off"]) > 0:
results["gen"][ix_(results["order"]["gen"]["status"]["off"], [PG, QG])] = 0
if len(results["order"]["branch"]["status"]["off"]) > 0:
results["branch"][ix_(results["order"]["branch"]["status"]["off"], [PF, QF, PT, QT])] = 0
if fname:
fd = None
try:
fd = open(fname, "a")
except Exception as detail:
stderr.write("Error opening %s: %s.\n" % (fname, detail))
finally:
if fd is not None:
printpf(results, fd, ppopt)
fd.close()
else:
printpf(results, stdout, ppopt)
## save solved case
if solvedcase:
savecase(solvedcase, results)
return results, success
0
Example 27
Project: PYPOWER Source File: scale_load.py
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
0
Example 28
Project: PYPOWER Source File: t_auction_pips.py
def t_auction_pips(quiet=False):
"""Tests for code in auction.py, using PIPS solver.
@author: Ray Zimmerman (PSERC Cornell)
"""
n_tests = 183
t_begin(n_tests, quiet)
try:
from pypower.extras.smartmarket import runmkt
except ImportError:
t_skip(n_tests, 'smartmarket code not available')
return
ppopt = ppoption
ppopt['OPF_VIOLATION'] = 1e-7
ppopt['PDIPM_GRADTOL'] = 1e-6
ppopt['PDIPM_COMPTOL'] = 1e-7
ppopt['PDIPM_COSTTOL'] = 5e-9
ppopt['OPF_ALG'] = 560
ppopt['OUT_ALL_LIM'] = 1
ppopt['OUT_BRANCH'] = 0
ppopt['OUT_SYS_SUM'] = 0
ppopt['OUT_ALL'] = 0
ppopt['VERBOSE'] = 0
q = array([
[12, 24, 24],
[12, 24, 24],
[12, 24, 24],
[12, 24, 24],
[12, 24, 24],
[12, 24, 24],
[10, 10, 10],
[10, 10, 10],
[10, 10, 10],
])
##----- one offer block marginal @ $50 -----
p = array([
[20, 50, 60],
[20, 40, 70],
[20, 42, 80],
[20, 44, 90],
[20, 46, 75],
[20, 48, 60],
[100, 70, 60],
[100, 50, 20],
[100, 60, 50]
])
t = 'one marginal offer @ $50, auction_type = 5'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
cq5 = cq.copy()
cp5 = cp.copy()
i2e = bus.bus_i
e2i = sparse((max(i2e), 1))
e2i[i2e] = range(bus.size())
G = find( isload(gen) == False ) ## real generators
L = find( isload(gen) ) ## dispatchable loads
Gbus = e2i[gen.gen_bus[G]]
Lbus = e2i[gen.gen_bus[L]]
Qfudge = zeros(p.shape)
Qfudge[L, :] = \
diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L :].shape)
t_is( cq[G[0], 1:3], [23.32, 0], 2, t )
t_is( cp[G[0], :], 50, 4, t )
t_is( cq[L[1], 0:2], [10, 0], 2, t )
t_is( cp[L[1], :], 54.0312, 4, t )
t_is( cp[G, 0], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
t_is( cp[L, 0], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )
lao_X = p(G[0], 1) / bus.lam_P[Gbus[0], LAM_P]
fro_X = p(G(5), 2) / bus.lam_P[Gbus[5], LAM_P]
lab_X = p(L(2), 1) / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
frb_X = p(L(1), 1) / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
t_is( lao_X, 1, 4, 'lao_X')
t_is( fro_X, 1.1324, 4, 'fro_X')
t_is( lab_X, 1.0787, 4, 'lab_X')
t_is( frb_X, 0.9254, 4, 'frb_X')
t = 'one marginal offer @ $50, auction_type = 1'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1110, 100, [], [], mpopt)
cp1 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 6, [t, ' : prices'] )
t = 'one marginal offer @ $50, auction_type = 2'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1120, 100, [], [], mpopt)
cp2 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp5[G, :] * fro_X, 8, [t, ' : gen prices'] )
t_is( cp[L[0:1], :], cp5[L[0:1], :] * fro_X, 8, [t, ' : load 1,2 prices'] )
t_is( cp[L[2], :], 60, 5, [t, ' : load 3 price'] ) ## clipped by accepted bid
t = 'one marginal offer @ $50, auction_type = 3'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1130, 100, [], [], mpopt)
cp3 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5 * lab_X, 8, [t, ' : prices'] )
t = 'one marginal offer @ $50, auction_type = 4'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1140, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], p[G[0], 1], 8, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp5[G[1:6], :] * frb_X, 8, [t, ' : gen 2-6 prices'] )
t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )
t = 'one marginal offer @ $50, auction_type = 6'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp3, 8, [t, ' : prices'] )
p2 = p.copy()
p2[L, :] = array([
[100, 100, 100],
[100, 0, 0],
[100, 100, 0]
])
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 5, [t, ' : quantities'] )
t_is( cp[G, :], cp5[G, :] * fro_X, 4, [t, ' : gen prices'] )
t_is( cp[L, :], cp5[L, :] * fro_X, 4, [t, ' : load prices'] ) ## load 3 not clipped as in FRO
t = 'one marginal offer @ $50, auction_type = 7'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1170, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5 * (lao_X + lab_X) / 2, 8, [t, ' : prices'] )
t_is( cp, (cp1 + cp3) / 2, 8, [t, ' : prices'] )
t = 'one marginal offer @ $50, auction_type = 8'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1180, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp1[G, :], 8, [t, ' : gen prices'] )
t_is( cp[L, :], cp3[L, :], 8, [t, ' : load prices'] )
t = 'one marginal offer @ $50, auction_type = 0'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1100, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, p, 8, [t, ' : prices'] )
##----- one bid block marginal @ $55 -----
p[L[1], 1] = 55
t = 'one marginal bid @ $55, auction_type = 5'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
cq5 = cq.copy()
cp5 = cp.copy()
Qfudge = zeros(p.shape)
Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
t_is( cq[G[0], 1:3], [24, 0], 2, t )
t_is( cp[G[0], :], 50.016, 3, t )
t_is( cq[L[1], 0:2], [10, 0.63], 2, t )
t_is( cp[L[1], :], 55, 4, t )
t_is( cp[G, 0], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
t_is( cp[L, 0], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )
lao_X = p[G[0], 1] / bus.lam_P[Gbus[0]]
fro_X = p[G[5], 2] / bus.lam_P[Gbus[5]]
lab_X = p[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
frb_X = p[L[2], 2] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
t_is( lao_X, 0.9997, 4, 'lao_X')
t_is( fro_X, 1.1111, 4, 'fro_X')
t_is( lab_X, 1, 4, 'lab_X')
t_is( frb_X, 0.8960, 4, 'frb_X')
t = 'one marginal bid @ $55, auction_type = 1'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1110, 100, [], [], mpopt)
cp1 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5 * lao_X, 8, [t, ' : prices'] )
t = 'one marginal bid @ $55, auction_type = 2'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1120, 100, [], [], mpopt)
cp2 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp5[G, :] * fro_X, 8, [t, ' : gen prices'] )
t_is( cp[L[0], :], cp5[L[0], :] * fro_X, 8, [t, ' : load 1 price'] )
t_is( cp[L[1], :], 55, 5, [t, ' : load 2 price'] )
t_is( cp[L[2], :], 60, 5, [t, ' : load 3 price'] )
t = 'one marginal bid @ $55, auction_type = 3'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1130, 100, [], [], mpopt)
cp3 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 7, [t, ' : prices'] )
t = 'one marginal bid @ $55, auction_type = 4'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1140, 100, [], [], mpopt)
cp4 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 50, 5, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp5[G[1:6], :] * frb_X, 8, [t, ' : gen 2-6 prices'] )
t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )
t = 'one marginal bid @ $55, auction_type = 6'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp1, 8, [t, ' : prices'] )
p2 = p.copy()
p2[G, :] = array([
[0, 0, 100],
[0, 0, 100],
[0, 0, 100],
[0, 0, 100],
[0, 0, 100],
[0, 0, 100]
])
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 3, [t, ' : quantities'] )
t_is( cp[G, :], cp5[G, :] * frb_X, 3, [t, ' : gen prices'] ) ## gen 1, not clipped this time
t_is( cp[L, :], cp4[L, :], 3, [t, ' : load prices'] )
t = 'one marginal bid @ $55, auction_type = 7'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1170, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5 * (lao_X + lab_X) / 2, 8, [t, ' : prices'] )
t_is( cp, (cp1 + cp3) / 2, 8, [t, ' : prices'] )
t = 'one marginal bid @ $55, auction_type = 8'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1180, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp1[G, :], 8, [t, ' : gen prices'] )
t_is( cp[L, :], cp3[L, :], 8, [t, ' : load prices'] )
t = 'one marginal bid @ $55, auction_type = 0'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1100, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, p, 8, [t, ' : prices'] )
##----- one bid block marginal @ $54.50 and one offer block marginal @ $50 -----
p[L[1], 1] = 54.5
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 5'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
cq5 = cq.copy()
cp5 = cp.copy()
Qfudge = zeros(p.shape)
Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
t_is( cq[G[0], 1:3], [23.74, 0], 2, t )
t_is( cp[G[0], :], 50, 4, t )
t_is( cq[L[1], 0:2], [10, 0.39], 2, t )
t_is( cp[L[1], :], 54.5, 4, t )
t_is( cp[G, 0], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
t_is( cp[L, 0], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )
lao_X = p[G[0], 1] / bus.lam_P[Gbus[0]]
fro_X = p[G[5], 2] / bus.lam_P[Gbus[5]]
lab_X = p[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
frb_X = p[L[2], 2] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
t_is( lao_X, 1, 4, 'lao_X')
t_is( fro_X, 1.1221, 4, 'fro_X')
t_is( lab_X, 1, 4, 'lab_X')
t_is( frb_X, 0.8976, 4, 'frb_X')
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 1'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1110, 100, [], [], mpopt)
cp1 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 4, [t, ' : prices'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 2'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1120, 100, [], [], mpopt)
cp2 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp5[G, :] * fro_X, 5, [t, ' : gen prices'] )
t_is( cp[L[0], :], cp5[L[0], :] * fro_X, 5, [t, ' : load 1 price'] )
t_is( cp[L[1], :], 54.5, 5, [t, ' : load 2 price'] )
t_is( cp[L[2], :], 60, 5, [t, ' : load 3 price'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 3'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1130, 100, [], [], mpopt)
cp3 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 6, [t, ' : prices'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 4'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1140, 100, [], [], mpopt)
cp4 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 50, 5, [t, ' : gen 1 price'] )
t_is( cp[G[1:5], :], cp5[G[1:5], :] * frb_X, 8, [t, ' : gen 2-5 prices'] )
t_is( cp[G[5], :], 48, 5, [t, ' : gen 6 price'] )
t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 6'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 4, [t, ' : prices'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 7'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1170, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 4, [t, ' : prices'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 8'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1180, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 4, [t, ' : prices'] )
t = 'marginal offer @ $50, bid @ $54.50, auction_type = 0'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1100, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, p, 8, [t, ' : prices'] )
##----- gen 1 at Pmin, load 3 block 2 marginal @ $60 -----
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 5'
p[L[1], 1] = 50 ## undo previous change
p2 = p.copy()
p2[G[0], 1:3] = [65, 65]
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1150, 100, [], [], mpopt)
Qfudge = zeros(p.shape)
Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
t_is( cp[G[0], :], 65, 4, [t, ' : gen 1 price'] )
t_is( cp[G[1], :], 54.2974, 4, [t, ' : gen 2 price'] )
cq5 = cq.copy()
cp5 = cp.copy()
cp_lam = cp5.copt()
cp_lam[0, :] = bus.lam_P[Gbus[0]] ## unclipped
lao_X = p2[G[5], 1] / bus.lam_P[Gbus[5]]
fro_X = p2[G[5], 2] / bus.lam_P[Gbus[5]]
lab_X = p2[L[2], 1] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
frb_X = p2[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
t_is( lao_X, 0.8389, 4, 'lao_X')
t_is( fro_X, 1.0487, 4, 'fro_X')
t_is( lab_X, 1, 4, 'lab_X')
t_is( frb_X, 0.8569, 4, 'frb_X')
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 1'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1110, 100, [], [], mpopt)
cp1 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 65, 8, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp_lam[G[1:6], :] * lao_X, 8, [t, ' : gen 2-6 prices'] )
t_is( cp[L, :], cp_lam[L, :] * lao_X, 8, [t, ' : load prices'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 2'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1120, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 65, 8, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp_lam[G[1:6], :] * fro_X, 8, [t, ' : gen 2-6 prices'] )
t_is( cp[L[0:2], :], cp_lam[L[0:2], :] * fro_X, 8, [t, ' : load 1-2 prices'] )
t_is( cp[L[2], :], 60, 8, [t, ' : load 3 price'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 3'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1130, 100, [], [], mpopt)
cp3 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 65, 8, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp_lam[G[1:6], :], 6, [t, ' : gen 2-6 prices'] )
t_is( cp[L, :], cp_lam[L, :], 6, [t, ' : load prices'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 4'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1140, 100, [], [], mpopt)
cp4 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 65, 5, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp5[G[1:6], :] * frb_X, 8, [t, ' : gen 2-6 prices'] )
t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 6'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp4, 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 7'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1170, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G[0], :], 65, 4, [t, ' : gen 1 price'] )
t_is( cp[G[1:6], :], cp_lam[G[1:6], :] * (lao_X + lab_X) / 2, 8, [t, ' : gen 2-6 prices'] )
t_is( cp[L, :], cp_lam[L, :] * (lao_X + lab_X) / 2, 8, [t, ' : load prices'] )
t_is( cp, (cp1 + cp3) / 2, 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 8'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1180, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp1[G, :], 8, [t, ' : prices'] )
t_is( cp[L, :], cp3[L, :], 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 0'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1100, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, p2, 8, [t, ' : prices'] )
##----- gen 1 at Pmin, gen 6 block 3 marginal @ $60 -----
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 5'
p2[L, :] = array([
[100, 100, 100],
[100, 0, 0],
[100, 100, 0]
])
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1150, 100, [], [], mpopt)
Qfudge = zeros(p.shape)
Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
t_is( cp[G[0], :], 65, 4, [t, ' : gen 1 price'] )
t_is( cp[G[1], :], 57.1612, 4, [t, ' : gen 2 price'] )
cq5 = cq.copy()
cp5 = cp.copy()
cp_lam = cp5.copy()
cp_lam[0, :] = bus.lamP[Gbus[0]] ## unclipped
lao_X = p2[G[5], 2] / bus.lam_P[Gbus[5]]
fro_X = p2[G[0], 2] / bus.lam_P[Gbus[0]]
lab_X = p2[L[2], 1] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
frb_X = p2[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
t_is( lao_X, 1, 4, 'lao_X')
t_is( fro_X, 1.1425, 4, 'fro_X')
t_is( lab_X, 1.5813, 4, 'lab_X')
t_is( frb_X, 0, 4, 'frb_X')
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 1'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1110, 100, [], [], mpopt)
cp1 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp5, 6, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 2'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1120, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp_lam * fro_X, 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 3'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1130, 100, [], [], mpopt)
cp3 = cp.copy()
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp_lam * lab_X, 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 4'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1140, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, 0], [654042444660], 4, [t, ' : gen prices'] )
t_is( cp[L, :], cp_lam[L, :] * frb_X, 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 6'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp_lam * fro_X, 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 7'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1170, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, cp_lam * (lao_X + lab_X) / 2, 8, [t, ' : prices'] )
t_is( cp, (cp_lam + cp3) / 2, 7, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 8'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1180, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp[G, :], cp5[G, :], 7, [t, ' : prices'] )
t_is( cp[L, :], cp3[L, :], 8, [t, ' : prices'] )
t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 0'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p2, 1100, 100, [], [], mpopt)
t_is( cq, cq5, 8, [t, ' : quantities'] )
t_is( cp, p2, 8, [t, ' : prices'] )
##----- gen 2 decommitted, one offer block marginal @ $60 -----
p[G[1], :] = p[G[1], :] + 100
t = 'price of decommited gen, auction_type = 5'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1150, 200, [], [], mpopt)
cp5 = cp.copy()
Qfudge = zeros(p.shape)
Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
t_is(sum(cq[1, :]), 0, 8, t)
t_is(cp[1, 0], 59.194, 3, t)
# Xo = p[0:6, :] / (diag(bus.lam_P[Gbus]) * ones(p[G, :].shape))
# ao = (cq[0:6, :] != 0)
# ro = (cq[0:6, :] == 0)
# Xb = p[6:9, :] / (diag(bus.lam_P[Lbus] + gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape))
# ab = (cq[6:9, :] != 0)
# rb = (cq[6:9, :] == 0)
# aXo = ao * Xo
# rXo = ro * Xo
# aXb = ab * Xb
# rXb = rb * Xb
lao_X = p[G[5], 2] / bus.lam_P[Gbus[5]]
fro_X = p[G[0], 2] / bus.lam_P[Gbus[0]]
lab_X = p[L[0], 1] / (bus.lam_P[Lbus[0]] + Qfudge[L[0], 0])
frb_X = p[L[0], 2] / (bus.lam_P[Lbus[0]] + Qfudge[L[0], 0])
t_is( lao_X, 1, 4, 'lao_X')
t_is( fro_X, 1.0212, 4, 'fro_X')
t_is( lab_X, 1.1649, 4, 'lab_X')
t_is( frb_X, 0.9985, 4, 'frb_X')
t = 'price of decommited gen, auction_type = 1'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1110, 200, [], [], mpopt)
t_is(cp[1, 0], 59.194, 3, t)
t = 'price of decommited gen, auction_type = 2'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1120, 200, [], [], mpopt)
t_is(cp[1, 0], cp5[1, 0] * fro_X, 3, t)
t = 'price of decommited gen, auction_type = 3'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1130, 200, [], [], mpopt)
t_is(cp[1, 0], cp5[1, 0] * lab_X, 3, t)
t = 'price of decommited gen, auction_type = 4'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1140, 200, [], [], mpopt)
t_is(cp[1, 0], cp5[1, 0] * frb_X, 3, t)
t = 'price of decommited gen, auction_type = 6'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1160, 200, [], [], mpopt)
t_is(cp[1, 0], cp5[1, 0] * fro_X, 3, t)
t = 'price of decommited gen, auction_type = 7'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1170, 200, [], [], mpopt)
t_is(cp[1, 0], cp5[1, 0] * (lao_X + lab_X) / 2, 3, t)
t = 'price of decommited gen, auction_type = 0'
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1100, 200, [], [], mpopt)
t_is(cp[1, 0], 120, 3, t)
t = 'single block, marginal offer @ $50, auction_type = 5'
q = array([
[60],
[36],
[36],
[36],
[36],
[36],
[30],
[10],
[20]
])
p = array([
[50],
[40],
[42],
[44],
[46],
[48],
[100],
[100],
[100]
])
MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
t_is( cq[G[0]], 35.32, 2, t )
t_is( cq[G[1:6]], q[G[1:6]], 8, [t, ' : gen qtys'] )
t_is( cp[G[0]], 50, 4, t )
t_is( cq[L], q[L], 8, [t, ' : load qtys'] )
t_is( cp[L[1], :], 54.03, 2, t )
t_is( cp[G], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
Qfudge = zeros(p.shape)
Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
t_is( cp[L], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )
t_end()
0
Example 29
Project: PYPOWER Source File: t_dcline.py
def t_dcline(quiet=False):
"""Tests for DC line extension in L{{toggle_dcline}.
@author: Ray Zimmerman (PSERC Cornell)
"""
num_tests = 50
t_begin(num_tests, quiet)
tdir = dirname(__file__)
casefile = join(tdir, 't_case9_dcline')
if quiet:
verbose = False
else:
verbose = False
t0 = ''
ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8,
PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9)
ppopt = ppoption(ppopt, OPF_ALG=560, OPF_ALG_DC=200)
ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose)
## set up indices
ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)]
ib_voltage = arange(VM, VA + 1)
ib_lam = arange(LAM_P, LAM_Q + 1)
ib_mu = arange(MU_VMAX, MU_VMIN + 1)
ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)]
ig_disp = array([PG, QG, VG])
ig_mu = arange(MU_PMAX, MU_QMIN + 1)
ibr_data = arange(ANGMAX + 1)
ibr_flow = arange(PF, QT + 1)
ibr_mu = array([MU_SF, MU_ST])
ibr_angmu = array([MU_ANGMIN, MU_ANGMAX])
## load case
ppc0 = loadcase(casefile)
del ppc0['dclinecost']
ppc = ppc0
ppc = toggle_dcline(ppc, 'on')
ppc = toggle_dcline(ppc, 'off')
ndc = ppc['dcline'].shape[0]
## run AC OPF w/o DC lines
t = ''.join([t0, 'AC OPF (no DC lines) : '])
r0 = runopf(ppc0, ppopt)
success = r0['success']
t_ok(success, [t, 'success'])
r = runopf(ppc, ppopt)
success = r['success']
t_ok(success, [t, 'success'])
t_is(r['f'], r0['f'], 8, [t, 'f'])
t_is( r['bus'][:,ib_data ], r0['bus'][:,ib_data ], 10, [t, 'bus data'])
t_is( r['bus'][:,ib_voltage], r0['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
t_is( r['bus'][:,ib_lam ], r0['bus'][:,ib_lam ], 3, [t, 'bus lambda'])
t_is( r['bus'][:,ib_mu ], r0['bus'][:,ib_mu ], 2, [t, 'bus mu'])
t_is( r['gen'][:,ig_data ], r0['gen'][:,ig_data ], 10, [t, 'gen data'])
t_is( r['gen'][:,ig_disp ], r0['gen'][:,ig_disp ], 3, [t, 'gen dispatch'])
t_is( r['gen'][:,ig_mu ], r0['gen'][:,ig_mu ], 3, [t, 'gen mu'])
t_is(r['branch'][:,ibr_data ], r0['branch'][:,ibr_data ], 10, [t, 'branch data'])
t_is(r['branch'][:,ibr_flow ], r0['branch'][:,ibr_flow ], 3, [t, 'branch flow'])
t_is(r['branch'][:,ibr_mu ], r0['branch'][:,ibr_mu ], 2, [t, 'branch mu'])
t = ''.join([t0, 'AC PF (no DC lines) : '])
ppc1 = {'baseMVA': r['baseMVA'],
'bus': r['bus'][:, :VMIN + 1].copy(),
'gen': r['gen'][:, :APF + 1].copy(),
'branch': r['branch'][:, :ANGMAX + 1].copy(),
'gencost': r['gencost'].copy(),
'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
ppc1['bus'][:, VM] = 1
ppc1['bus'][:, VA] = 0
rp = runpf(ppc1, ppopt)
success = rp['success']
t_ok(success, [t, 'success'])
t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch'])
t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow'])
## run with DC lines
t = ''.join([t0, 'AC OPF (with DC lines) : '])
ppc = toggle_dcline(ppc, 'on')
r = runopf(ppc, ppopt)
success = r['success']
t_ok(success, [t, 'success'])
expected = array([
[10, 8.9, -10, 10, 1.0674, 1.0935],
[2.2776, 2.2776, 0, 0, 1.0818, 1.0665],
[0, 0, 0, 0, 1.0000, 1.0000],
[10, 9.5, 0.0563, -10, 1.0778, 1.0665]
])
t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V'])
expected = array([
[0, 0.8490, 0.6165, 0, 0, 0.2938],
[0, 0, 0, 0.4290, 0.0739, 0],
[0, 0, 0, 0, 0, 0],
[0, 7.2209, 0, 0, 0.0739, 0]
])
t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu'])
t = ''.join([t0, 'AC PF (with DC lines) : '])
ppc1 = {'baseMVA': r['baseMVA'],
'bus': r['bus'][:, :VMIN + 1].copy(),
'gen': r['gen'][:, :APF + 1].copy(),
'branch': r['branch'][:, :ANGMAX + 1].copy(),
'gencost': r['gencost'].copy(),
'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
ppc1 = toggle_dcline(ppc1, 'on')
ppc1['bus'][:, VM] = 1
ppc1['bus'][:, VA] = 0
rp = runpf(ppc1, ppopt)
success = rp['success']
t_ok(success, [t, 'success'])
t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
#t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch'])
t_is( rp['gen'][:2,ig_disp ], r['gen'][:2,ig_disp ], 3, [t, 'gen dispatch'])
t_is( rp['gen'][2,PG ], r['gen'][2,PG ], 3, [t, 'gen dispatch'])
t_is( rp['gen'][2,QG]+rp['dcline'][0,c.QF], r['gen'][2,QG]+r['dcline'][0,c.QF], 3, [t, 'gen dispatch'])
t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow'])
## add appropriate P and Q injections and check angles and generation when running PF
t = ''.join([t0, 'AC PF (with equivalent injections) : '])
ppc1 = {'baseMVA': r['baseMVA'],
'bus': r['bus'][:, :VMIN + 1].copy(),
'gen': r['gen'][:, :APF + 1].copy(),
'branch': r['branch'][:, :ANGMAX + 1].copy(),
'gencost': r['gencost'].copy(),
'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
ppc1['bus'][:, VM] = 1
ppc1['bus'][:, VA] = 0
for k in range(ndc):
if ppc1['dcline'][k, c.BR_STATUS]:
ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS])
tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS])
ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF]
ppc1['bus'][ff, QD] = ppc1['bus'][ff, QD] - r['dcline'][k, c.QF]
ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT]
ppc1['bus'][tt, QD] = ppc1['bus'][tt, QD] - r['dcline'][k, c.QT]
ppc1['bus'][ff, VM] = r['dcline'][k, c.VF]
ppc1['bus'][tt, VM] = r['dcline'][k, c.VT]
ppc1['bus'][ff, BUS_TYPE] = PV
ppc1['bus'][tt, BUS_TYPE] = PV
rp = runpf(ppc1, ppopt)
success = rp['success']
t_ok(success, [t, 'success'])
t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch'])
t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow'])
## test DC OPF
t = ''.join([t0, 'DC OPF (with DC lines) : '])
ppc = ppc0.copy()
ppc['gen'][0, PMIN] = 10
ppc['branch'][4, RATE_A] = 100
ppc = toggle_dcline(ppc, 'on')
r = rundcopf(ppc, ppopt)
success = r['success']
t_ok(success, [t, 'success'])
expected = array([
[10, 8.9, 0, 0, 1.01, 1],
[2, 2, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 1],
[10, 9.5, 0, 0, 1, 0.98]
])
t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V'])
expected = array([
[0, 1.8602, 0, 0, 0, 0],
[1.8507, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0.2681, 0, 0, 0, 0]
])
t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu'])
t = ''.join([t0, 'DC PF (with DC lines) : '])
ppc1 = {'baseMVA': r['baseMVA'],
'bus': r['bus'][:, :VMIN + 1].copy(),
'gen': r['gen'][:, :APF + 1].copy(),
'branch': r['branch'][:, :ANGMAX + 1].copy(),
'gencost': r['gencost'].copy(),
'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
ppc1 = toggle_dcline(ppc1, 'on')
ppc1['bus'][:, VA] = 0
rp = rundcpf(ppc1, ppopt)
success = rp['success']
t_ok(success, [t, 'success'])
t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch'])
t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow'])
## add appropriate P injections and check angles and generation when running PF
t = ''.join([t0, 'DC PF (with equivalent injections) : '])
ppc1 = {'baseMVA': r['baseMVA'],
'bus': r['bus'][:, :VMIN + 1].copy(),
'gen': r['gen'][:, :APF + 1].copy(),
'branch': r['branch'][:, :ANGMAX + 1].copy(),
'gencost': r['gencost'].copy(),
'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
ppc1['bus'][:, VA] = 0
for k in range(ndc):
if ppc1['dcline'][k, c.BR_STATUS]:
ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS])
tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS])
ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF]
ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT]
ppc1['bus'][ff, BUS_TYPE] = PV
ppc1['bus'][tt, BUS_TYPE] = PV
rp = rundcpf(ppc1, ppopt)
success = rp['success']
t_ok(success, [t, 'success'])
t_is( rp['bus'][:,ib_voltage], r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
t_is( rp['gen'][:,ig_disp ], r['gen'][:,ig_disp ], 3, [t, 'gen dispatch'])
t_is(rp['branch'][:,ibr_flow ], r['branch'][:,ibr_flow ], 3, [t, 'branch flow'])
## run with DC lines
t = ''.join([t0, 'AC OPF (with DC lines + poly cost) : '])
ppc = loadcase(casefile)
ppc = toggle_dcline(ppc, 'on')
r = runopf(ppc, ppopt)
success = r['success']
t_ok(success, [t, 'success'])
expected1 = array([
[10, 8.9, -10, 10, 1.0663, 1.0936],
[7.8429, 7.8429, 0, 0, 1.0809, 1.0667],
[0, 0, 0, 0, 1.0000, 1.0000],
[6.0549, 5.7522, -0.5897, -10, 1.0778, 1.0667]
])
t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V'])
expected2 = array([
[0, 0.7605, 0.6226, 0, 0, 0.2980],
[0, 0, 0, 0.4275, 0.0792, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0.0792, 0]
])
t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu'])
ppc['dclinecost'][3, :8] = array([2, 0, 0, 4, 0, 0, 7.3, 0])
r = runopf(ppc, ppopt)
success = r['success']
t_ok(success, [t, 'success'])
t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V'])
t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu'])
t = ''.join([t0, 'AC OPF (with DC lines + pwl cost) : '])
ppc['dclinecost'][3, :8] = array([1, 0, 0, 2, 0, 0, 10, 73])
r = runopf(ppc, ppopt)
success = r['success']
t_ok(success, [t, 'success'])
t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V'])
t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu'])
t_end()
0
Example 30
Project: PYPOWER Source File: t_makePTDF.py
def t_makePTDF(quiet=False):
"""Tests for C{makePTDF}.
@author: Ray Zimmerman (PSERC Cornell)
"""
ntests = 24
t_begin(ntests, quiet)
tdir = dirname(__file__)
casefile = join(tdir, 't_case9_opf')
verbose = 0#not quiet
## load case
ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0)
r = rundcopf(casefile, ppopt)
baseMVA, bus, gen, branch = r['baseMVA'], r['bus'], r['gen'], r['branch']
_, bus, gen, branch = ext2int1(bus, gen, branch)
nb = bus.shape[0]
nbr = branch.shape[0]
ng = gen.shape[0]
## compute injections and flows
Cg = sparse((ones(ng), (gen[:, GEN_BUS], arange(ng))), (nb, ng))
Pg = Cg * gen[:, PG]
Pd = bus[:, PD]
P = Pg - Pd
ig = find(P > 0)
il = find(P <= 0)
F = branch[:, PF]
## create corresponding slack distribution matrices
e1 = zeros((nb, 1)); e1[0] = 1
e4 = zeros((nb, 1)); e4[3] = 1
D1 = eye(nb, nb) - dot(e1, ones((1, nb)))
D4 = eye(nb, nb) - dot(e4, ones((1, nb)))
Deq = eye(nb, nb) - ones((nb, 1)) / nb * ones((1, nb))
Dg = eye(nb) - matrix( Pd / sum(Pd) ).T * ones(nb)
Dd = eye(nb) - matrix( Pg / sum(Pg) ).T * ones(nb)
## create some PTDF matrices
H1 = makePTDF(baseMVA, bus, branch, 0)
H4 = makePTDF(baseMVA, bus, branch, 3)
Heq = makePTDF(baseMVA, bus, branch, ones(nb))
Hg = makePTDF(baseMVA, bus, branch, Pd)
Hd = makePTDF(baseMVA, bus, branch, Pg)
## matrices get properly transformed by slack dist matrices
t_is(H1, dot(H1, D1), 8, 'H1 == H1 * D1')
t_is(H4, dot(H1, D4), 8, 'H4 == H1 * D4')
t_is(Heq, dot(H1, Deq), 8, 'Heq == H1 * Deq')
t_is(Hg, dot(H1, Dg), 8, 'Hg == H1 * Dg')
t_is(Hd, dot(H1, Dd), 8, 'Hd == H1 * Dd')
t_is(H1, dot(Heq, D1), 8, 'H1 == Heq * D1')
t_is(H4, dot(Heq, D4), 8, 'H4 == Heq * D4')
t_is(Heq, dot(Heq, Deq), 8, 'Heq == Heq * Deq')
t_is(Hg, dot(Heq, Dg), 8, 'Hg == Heq * Dg')
t_is(Hd, dot(Heq, Dd), 8, 'Hd == Heq * Dd')
t_is(H1, dot(Hg, D1), 8, 'H1 == Hg * D1')
t_is(H4, dot(Hg, D4), 8, 'H4 == Hg * D4')
t_is(Heq, dot(Hg, Deq), 8, 'Heq == Hg * Deq')
t_is(Hg, dot(Hg, Dg), 8, 'Hg == Hg * Dg')
t_is(Hd, dot(Hg, Dd), 8, 'Hd == Hg * Dd')
## PTDFs can reconstruct flows
t_is(F, dot(H1, P), 3, 'Flow == H1 * P')
t_is(F, dot(H4, P), 3, 'Flow == H4 * P')
t_is(F, dot(Heq, P), 3, 'Flow == Heq * P')
t_is(F, dot(Hg, P), 3, 'Flow == Hg * P')
t_is(F, dot(Hd, P), 3, 'Flow == Hd * P')
## other
t_is(F, dot(Hg, Pg), 3, 'Flow == Hg * Pg')
t_is(F, dot(Hd, (-Pd)), 3, 'Flow == Hd * (-Pd)')
t_is(zeros(nbr), dot(Hg, (-Pd)), 3, 'zeros == Hg * (-Pd)')
t_is(zeros(nbr), dot(Hd, Pg), 3, 'zeros == Hd * Pg')
t_end()
0
Example 31
Project: PYPOWER Source File: t_off2case.py
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()
0
Example 32
Project: PYPOWER Source File: t_runmarket.py
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
0
Example 33
Project: PYPOWER Source File: t_scale_load.py
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()
0
Example 34
Project: PYPOWER Source File: t_total_load.py
def t_total_load(quiet=False):
"""Tests for code in C{total_load}.
@author: Ray Zimmerman (PSERC Cornell)
"""
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()
0
Example 35
Project: PYPOWER Source File: toggle_dcline.py
def toggle_dcline(ppc, on_off):
"""Enable or disable DC line modeling.
Enables or disables a set of OPF userfcn callbacks to implement
DC lines as a pair of linked generators. While it uses the OPF
extension mechanism, this implementation works for simple power
flow as well as OPF problems.
These callbacks expect to find a 'dcline' field in the input MPC,
where MPC.dcline is an ndc x 17 matrix with columns as defined
in IDX_DCLINE, where ndc is the number of DC lines.
The 'int2ext' callback also packages up flow results and stores them
in appropriate columns of MPC.dcline.
NOTE: Because of the way this extension modifies the number of
rows in the gen and gencost matrices, caution must be taken
when using it with other extensions that deal with generators.
Examples:
ppc = loadcase('t_case9_dcline')
ppc = toggle_dcline(ppc, 'on')
results1 = runpf(ppc)
results2 = runopf(ppc)
@see: L{idx_dcline}, L{add_userfcn}, L{remove_userfcn}, L{run_userfcn}.
"""
if on_off == 'on':
## define named indices into data matrices
c = idx_dcline.c
## check for proper input data
if 'dcline' not in ppc or ppc['dcline'].shape[1] < c["LOSS1"] + 1:
raise ValueError('toggle_dcline: case must contain a '
'\'dcline\' field, an ndc x %d matrix.', c["LOSS1"])
if 'dclinecost' in ppc and ppc['dcline'].shape[0] != ppc['dclinecost'].shape[0]:
raise ValueError('toggle_dcline: number of rows in \'dcline\''
' field (%d) and \'dclinecost\' field (%d) do not match.' %
(ppc['dcline'].shape[0], ppc['dclinecost'].shape[0]))
k = find(ppc['dcline'][:, c["LOSS1"]] < 0)
if len(k) > 0:
warn('toggle_dcline: linear loss term is negative for DC line '
'from bus %d to %d\n' %
ppc['dcline'][k, c['F_BUS']:c['T_BUS'] + 1].T)
## add callback functions
## note: assumes all necessary data included in 1st arg (ppc, om, results)
## so, no additional explicit args are needed
ppc = add_userfcn(ppc, 'ext2int', userfcn_dcline_ext2int)
ppc = add_userfcn(ppc, 'formulation', userfcn_dcline_formulation)
ppc = add_userfcn(ppc, 'int2ext', userfcn_dcline_int2ext)
ppc = add_userfcn(ppc, 'printpf', userfcn_dcline_printpf)
ppc = add_userfcn(ppc, 'savecase', userfcn_dcline_savecase)
elif on_off == 'off':
ppc = remove_userfcn(ppc, 'savecase', userfcn_dcline_savecase)
ppc = remove_userfcn(ppc, 'printpf', userfcn_dcline_printpf)
ppc = remove_userfcn(ppc, 'int2ext', userfcn_dcline_int2ext)
ppc = remove_userfcn(ppc, 'formulation', userfcn_dcline_formulation)
ppc = remove_userfcn(ppc, 'ext2int', userfcn_dcline_ext2int)
else:
raise ValueError('toggle_dcline: 2nd argument must be either '
'\'on\' or \'off\'')
return ppc
0
Example 36
Project: PYPOWER Source File: toggle_dcline.py
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
0
Example 37
Project: PYPOWER Source File: toggle_dcline.py
def userfcn_dcline_int2ext(results, args):
"""This is the 'int2ext' stage userfcn callback that converts everything
back to external indexing and packages up the results. It expects to
find a 'dcline' field in the results struct as described for ppc
above. It also expects that the last 2*ndc entries in the gen and
gencost matrices correspond to the in-service DC lines (where ndc is
the number of rows in MPC.dcline. These extra rows are removed from
gen and gencost and the flow is taken from the PG of these gens and
placed in the flow column of the appropiate dcline row. The
optional args are not currently used.
"""
c = idx_dcline.c
## initialize some things
o = results['order']
k = find(o['ext']['dcline'][:, c['BR_STATUS']])
ndc = len(k) ## number of in-service DC lines
ng = results['gen'].shape[0] - 2*ndc; ## number of original gens/disp loads
## extract dummy gens
fg = results['gen'][ng:ng + ndc, :]
tg = results['gen'][ng + ndc:ng + 2 * ndc, :]
## remove dummy gens
#results['gen'] = results['gen'][:ng + 1, :]
#results['gencost'] = results['gencost'][:ng + 1, :]
results['gen'] = results['gen'][:ng, :]
results['gencost'] = results['gencost'][:ng, :]
## get the solved flows
results['dcline'][:, c['PF']] = -fg[:, PG]
results['dcline'][:, c['PT']] = tg[:, PG]
results['dcline'][:, c['QF']] = fg[:, QG]
results['dcline'][:, c['QT']] = tg[:, QG]
results['dcline'][:, c['VF']] = fg[:, VG]
results['dcline'][:, c['VT']] = tg[:, VG]
if fg.shape[1] >= MU_QMIN:
results['dcline'] = c_[results['dcline'], zeros((ndc, 6))]
results['dcline'][:, c['MU_PMIN'] ] = fg[:, MU_PMAX] + tg[:, MU_PMIN]
results['dcline'][:, c['MU_PMAX'] ] = fg[:, MU_PMIN] + tg[:, MU_PMAX]
results['dcline'][:, c['MU_QMINF']] = fg[:, MU_QMIN]
results['dcline'][:, c['MU_QMAXF']] = fg[:, MU_QMAX]
results['dcline'][:, c['MU_QMINT']] = tg[:, MU_QMIN]
results['dcline'][:, c['MU_QMAXT']] = tg[:, MU_QMAX]
results['order']['int'] = {}
##----- convert stuff back to external indexing -----
results['order']['int']['dcline'] = results['dcline'] ## save internal version
## copy results to external version
o['ext']['dcline'][k, c['PF']:c['VT'] + 1] = results['dcline'][:, c['PF']:c['VT'] + 1]
if results['dcline'].shape[1] == c['MU_QMAXT'] + 1:
o['ext']['dcline'] = c_[o['ext']['dcline'], zeros((ndc, 6))]
o['ext']['dcline'][k, c['MU_PMIN']:c['MU_QMAXT'] + 1] = \
results['dcline'][:, c['MU_PMIN']:c['MU_QMAXT'] + 1]
results['dcline'] = o['ext']['dcline'] ## use external version
return results
0
Example 38
Project: PYPOWER Source File: toggle_dcline.py
def userfcn_dcline_printpf(results, fd, ppopt, args):
"""This is the 'printpf' stage userfcn callback that pretty-prints the
results. It expects a results struct, a file descriptor and a MATPOWER
options vector. The optional args are not currently used.
"""
## define named indices into data matrices
c = idx_dcline.c
## options
OUT_ALL = ppopt['OUT_ALL']
OUT_BRANCH = OUT_ALL == 1 or (OUT_ALL == -1 and ppopt['OUT_BRANCH'])
if OUT_ALL == -1:
OUT_ALL_LIM = ppopt['OUT_ALL_LIM']
elif OUT_ALL == 1:
OUT_ALL_LIM = 2
else:
OUT_ALL_LIM = 0
if OUT_ALL_LIM == -1:
OUT_LINE_LIM = ppopt['OUT_LINE_LIM']
else:
OUT_LINE_LIM = OUT_ALL_LIM
ctol = ppopt['OPF_VIOLATION'] ## constraint violation tolerance
ptol = 1e-4 ## tolerance for displaying shadow prices
##----- print results -----
dc = results['dcline']
ndc = dc.shape[0]
kk = find(dc[:, c['BR_STATUS']] != 0)
if OUT_BRANCH:
fd.write('\n================================================================================')
fd.write('\n| DC Line Data |')
fd.write('\n================================================================================')
fd.write('\n Line From To Power Flow Loss Reactive Inj (MVAr)')
fd.write('\n # Bus Bus From (MW) To (MW) (MW) From To ')
fd.write('\n------ ------ ------ --------- --------- --------- --------- ---------')
loss = 0
for k in range(ndc):
if dc[k, c['BR_STATUS']]: ## status on
fd.write('\n{0:5.0f}{1:8.0f}{2:8.0f}{3:11.2f}{4:11.2f}{5:11.2f}{6:11.2f}{7:11.2f}'.format(*r_[k, dc[k, c['F_BUS']:c['T_BUS'] + 1], dc[k, c['PF']:c['PT'] + 1],dc[k, c['PF']] - dc[k, c['PT']], dc[k, c['QF']:c['QT'] + 1]]))
loss = loss + dc[k, c['PF']] - dc[k, c['PT']]
else:
fd.write('\n%5d%8d%8d%11s%11s%11s%11s%11s' %
(k, dc[k, c['F_BUS']:c['T_BUS'] + 1], '- ', '- ', '- ', '- ', '- '))
fd.write('\n ---------')
fd.write('\n Total:{0:11.2f}\n'.format(loss))
if OUT_LINE_LIM == 2 or (OUT_LINE_LIM == 1 and
(any(dc[kk, c['PF']] > dc[kk, c['PMAX']] - ctol) or
any(dc[kk, c['MU_PMIN']] > ptol) or
any(dc[kk, c['MU_PMAX']] > ptol))):
fd.write('\n================================================================================')
fd.write('\n| DC Line Constraints |')
fd.write('\n================================================================================')
fd.write('\n Line From To Minimum Actual Flow Maximum')
fd.write('\n # Bus Bus Pmin mu Pmin (MW) Pmax Pmax mu ')
fd.write('\n------ ------ ------ --------- --------- --------- --------- ---------')
for k in range(ndc):
if OUT_LINE_LIM == 2 or (OUT_LINE_LIM == 1 and
(dc[k, c['PF']] > dc[k, c['PMAX']] - ctol or
dc[k, c['MU_PMIN']] > ptol or
dc[k, c['MU_PMAX']] > ptol)):
if dc[k, c['BR_STATUS']]: ## status on
fd.write('\n{0:5.0f}{1:8.0f}{2:8.0f}'.format(*r_[k, dc[k, c['F_BUS']:c['T_BUS'] + 1]]))
#fd.write('\n%5d%8d%8d' % (k + 1, dc[k, c['F_BUS']:c['T_BUS'] + 1] ))
if dc[k, c['MU_PMIN']] > ptol:
fd.write('{0:11.3f}'.format(dc[k, c['MU_PMIN']]) )
else:
fd.write('%11s' % ('- '))
fd.write('{0:11.2f}{1:11.2f}{2:11.2f}' \
.format(*r_[dc[k, c['PMIN']], dc[k, c['PF']], dc[k, c['PMAX']]]))
if dc[k, c['MU_PMAX']] > ptol:
fd.write('{0:11.3f}'.format(dc[k, c['MU_PMAX']]))
else:
fd.write('%11s' % ('- '))
else:
fd.write('\n%5d%8d%8d%11s%11s%11s%11s%11s' %
(k, dc[k, c['F_BUS']:c['T_BUS'] + 1], '- ', '- ', '- ', '- ', '- '))
fd.write('\n')
return results
0
Example 39
Project: PYPOWER Source File: toggle_iflims.py
def userfcn_iflims_ext2int(ppc, *args):
"""This is the 'ext2int' stage userfcn callback that prepares the input
data for the formulation stage. It expects to find an 'if' field in
ppc as described above. The optional args are not currently used.
"""
## initialize some things
ifmap = ppc['if']['map']
o = ppc['order']
nl0 = o['ext']['branch'].shape[0] ## original number of branches
nl = ppc['branch'].shape[0] ## number of on-line branches
## save if.map for external indexing
ppc['order']['ext']['ifmap'] = ifmap
##----- convert stuff to internal indexing -----
e2i = zeros(nl0)
e2i[o['branch']['status']['on']] = arange(nl) ## ext->int branch index mapping
d = sign(ifmap[:, 1])
br = abs(ifmap[:, 1]).astype(int)
ifmap[:, 1] = d * e2i[br]
ifmap = delete(ifmap, find(ifmap[:, 1] == 0), 0) ## delete branches that are out
ppc['if']['map'] = ifmap
return ppc
0
Example 40
Project: PYPOWER Source File: toggle_reserves.py
def userfcn_reserves_ext2int(ppc, *args):
"""This is the 'ext2int' stage userfcn callback that prepares the input
data for the formulation stage. It expects to find a 'reserves' field
in ppc as described above. The optional args are not currently used.
"""
## initialize some things
r = ppc['reserves']
o = ppc['order']
ng0 = o['ext']['gen'].shape[0] ## number of original gens (+ disp loads)
nrz = r['req'].shape[0] ## number of reserve zones
if nrz > 1:
ppc['reserves']['rgens'] = any(r['zones'], 0) ## mask of gens available to provide reserves
else:
ppc['reserves']['rgens'] = r['zones']
igr = find(ppc['reserves']['rgens']) ## indices of gens available to provide reserves
ngr = len(igr) ## number of gens available to provide reserves
## check data for consistent dimensions
if r['zones'].shape[0] != nrz:
stderr.write('userfcn_reserves_ext2int: the number of rows in ppc[\'reserves\'][\'req\'] (%d) and ppc[\'reserves\'][\'zones\'] (%d) must match\n' % (nrz, r['zones'].shape[0]))
if (r['cost'].shape[0] != ng0) & (r['cost'].shape[0] != ngr):
stderr.write('userfcn_reserves_ext2int: the number of rows in ppc[\'reserves\'][\'cost\'] (%d) must equal the total number of generators (%d) or the number of generators able to provide reserves (%d)\n' % (r['cost'].shape[0], ng0, ngr))
if 'qty' in r:
if r['qty'].shape[0] != r['cost'].shape[0]:
stderr.write('userfcn_reserves_ext2int: ppc[\'reserves\'][\'cost\'] (%d x 1) and ppc[\'reserves\'][\'qty\'] (%d x 1) must be the same dimension\n' % (r['cost'].shape[0], r['qty'].shape[0]))
## convert both cost and qty from ngr x 1 to full ng x 1 vectors if necessary
if r['cost'].shape[0] < ng0:
if 'original' not in ppc['reserves']:
ppc['reserves']['original'] = {}
ppc['reserves']['original']['cost'] = r['cost'].copy() ## save original
cost = zeros(ng0)
cost[igr] = r['cost']
ppc['reserves']['cost'] = cost
if 'qty' in r:
ppc['reserves']['original']['qty'] = r['qty'].copy() ## save original
qty = zeros(ng0)
qty[igr] = r['qty']
ppc['reserves']['qty'] = qty
##----- convert stuff to internal indexing -----
## convert all reserve parameters (zones, costs, qty, rgens)
if 'qty' in r:
ppc = e2i_field(ppc, ['reserves', 'qty'], 'gen')
ppc = e2i_field(ppc, ['reserves', 'cost'], 'gen')
ppc = e2i_field(ppc, ['reserves', 'zones'], 'gen', 1)
ppc = e2i_field(ppc, ['reserves', 'rgens'], 'gen', 1)
## save indices of gens available to provide reserves
ppc['order']['ext']['reserves']['igr'] = igr ## external indexing
ppc['reserves']['igr'] = find(ppc['reserves']['rgens']) ## internal indexing
return ppc
0
Example 41
Project: PYPOWER Source File: toggle_reserves.py
def userfcn_reserves_formulation(om, *args):
"""This is the 'formulation' stage userfcn callback that defines the
user costs and constraints for fixed reserves. It expects to find
a 'reserves' field in the ppc stored in om, as described above.
By the time it is passed to this callback, ppc['reserves'] should
have two additional fields:
- C{igr} C{1 x ngr}, indices of generators available for reserves
- C{rgens} C{1 x ng}, 1 if gen avaiable for reserves, 0 otherwise
It is also assumed that if cost or qty were C{ngr x 1}, they have been
expanded to C{ng x 1} and that everything has been converted to
internal indexing, i.e. all gens are on-line (by the 'ext2int'
callback). The optional args are not currently used.
"""
## initialize some things
ppc = om.get_ppc()
r = ppc['reserves']
igr = r['igr'] ## indices of gens available to provide reserves
ngr = len(igr) ## number of gens available to provide reserves
ng = ppc['gen'].shape[0] ## number of on-line gens (+ disp loads)
## variable bounds
Rmin = zeros(ngr) ## bound below by 0
Rmax = Inf * ones(ngr) ## bound above by ...
k = find(ppc['gen'][igr, RAMP_10])
Rmax[k] = ppc['gen'][igr[k], RAMP_10] ## ... ramp rate and ...
if 'qty' in r:
k = find(r['qty'][igr] < Rmax)
Rmax[k] = r['qty'][igr[k]] ## ... stated max reserve qty
Rmax = Rmax / ppc['baseMVA']
## constraints
I = speye(ngr, ngr, format='csr') ## identity matrix
Ar = hstack([sparse((ones(ngr), (arange(ngr), igr)), (ngr, ng)), I], 'csr')
ur = ppc['gen'][igr, PMAX] / ppc['baseMVA']
lreq = r['req'] / ppc['baseMVA']
## cost
Cw = r['cost'][igr] * ppc['baseMVA'] ## per unit cost coefficients
## add them to the model
om.add_vars('R', ngr, [], Rmin, Rmax)
om.add_constraints('Pg_plus_R', Ar, [], ur, ['Pg', 'R'])
om.add_constraints('Rreq', sparse( r['zones'][:, igr] ), lreq, [], ['R'])
om.add_costs('Rcost', {'N': I, 'Cw': Cw}, ['R'])
return om
0
Example 42
Project: PYPOWER Source File: toggle_reserves.py
def userfcn_reserves_int2ext(results, *args):
"""This is the 'int2ext' stage userfcn callback that converts everything
back to external indexing and packages up the results. It expects to
find a 'reserves' field in the results struct as described for ppc
above, including the two additional fields 'igr' and 'rgens'. It also
expects the results to contain a variable 'R' and linear constraints
'Pg_plus_R' and 'Rreq' which are used to populate output fields in
results.reserves. The optional args are not currently used.
"""
## initialize some things
r = results['reserves']
## grab some info in internal indexing order
igr = r['igr'] ## indices of gens available to provide reserves
ng = results['gen'].shape[0] ## number of on-line gens (+ disp loads)
##----- convert stuff back to external indexing -----
## convert all reserve parameters (zones, costs, qty, rgens)
if 'qty' in r:
results = i2e_field(results, ['reserves', 'qty'], ordering='gen')
results = i2e_field(results, ['reserves', 'cost'], ordering='gen')
results = i2e_field(results, ['reserves', 'zones'], ordering='gen', dim=1)
results = i2e_field(results, ['reserves', 'rgens'], ordering='gen', dim=1)
results['order']['int']['reserves']['igr'] = results['reserves']['igr'] ## save internal version
results['reserves']['igr'] = results['order']['ext']['reserves']['igr'] ## use external version
r = results['reserves'] ## update
o = results['order'] ## update
## grab same info in external indexing order
igr0 = r['igr'] ## indices of gens available to provide reserves
ng0 = o['ext']['gen'].shape[0] ## number of gens (+ disp loads)
##----- results post-processing -----
## get the results (per gen reserves, multipliers) with internal gen indexing
## and convert from p.u. to per MW units
_, Rl, Ru = results['om'].getv('R')
R = zeros(ng)
Rmin = zeros(ng)
Rmax = zeros(ng)
mu_l = zeros(ng)
mu_u = zeros(ng)
mu_Pmax = zeros(ng)
R[igr] = results['var']['val']['R'] * results['baseMVA']
Rmin[igr] = Rl * results['baseMVA']
Rmax[igr] = Ru * results['baseMVA']
mu_l[igr] = results['var']['mu']['l']['R'] / results['baseMVA']
mu_u[igr] = results['var']['mu']['u']['R'] / results['baseMVA']
mu_Pmax[igr] = results['lin']['mu']['u']['Pg_plus_R'] / results['baseMVA']
## store in results in results struct
z = zeros(ng0)
results['reserves']['R'] = i2e_data(results, R, z, 'gen')
results['reserves']['Rmin'] = i2e_data(results, Rmin, z, 'gen')
results['reserves']['Rmax'] = i2e_data(results, Rmax, z, 'gen')
if 'mu' not in results['reserves']:
results['reserves']['mu'] = {}
results['reserves']['mu']['l'] = i2e_data(results, mu_l, z, 'gen')
results['reserves']['mu']['u'] = i2e_data(results, mu_u, z, 'gen')
results['reserves']['mu']['Pmax'] = i2e_data(results, mu_Pmax, z, 'gen')
results['reserves']['prc'] = z
for k in igr0:
iz = find(r['zones'][:, k])
results['reserves']['prc'][k] = sum(results['lin']['mu']['l']['Rreq'][iz]) / results['baseMVA']
results['reserves']['totalcost'] = results['cost']['Rcost']
## replace ng x 1 cost, qty with ngr x 1 originals
if 'original' in r:
if 'qty' in r:
results['reserves']['qty'] = r['original']['qty']
results['reserves']['cost'] = r['original']['cost']
del results['reserves']['original']
return results
0
Example 43
Project: PYPOWER Source File: toggle_reserves.py
def userfcn_reserves_printpf(results, fd, ppopt, *args):
"""This is the 'printpf' stage userfcn callback that pretty-prints the
results. It expects a C{results} dict, a file descriptor and a PYPOWER
options vector. The optional args are not currently used.
"""
##----- print results -----
r = results['reserves']
nrz = r['req'].shape[0]
OUT_ALL = ppopt['OUT_ALL']
if OUT_ALL != 0:
fd.write('\n================================================================================')
fd.write('\n| Reserves |')
fd.write('\n================================================================================')
fd.write('\n Gen Bus Status Reserves Price')
fd.write('\n # # (MW) ($/MW) Included in Zones ...')
fd.write('\n---- ----- ------ -------- -------- ------------------------')
for k in r['igr']:
iz = find(r['zones'][:, k])
fd.write('\n%3d %6d %2d ' % (k, results['gen'][k, GEN_BUS], results['gen'][k, GEN_STATUS]))
if (results['gen'][k, GEN_STATUS] > 0) & (abs(results['reserves']['R'][k]) > 1e-6):
fd.write('%10.2f' % results['reserves']['R'][k])
else:
fd.write(' - ')
fd.write('%10.2f ' % results['reserves']['prc'][k])
for i in range(len(iz)):
if i != 0:
fd.write(', ')
fd.write('%d' % iz[i])
fd.write('\n --------')
fd.write('\n Total:%10.2f Total Cost: $%.2f' %
(sum(results['reserves']['R'][r['igr']]), results['reserves']['totalcost']))
fd.write('\n')
fd.write('\nZone Reserves Price ')
fd.write('\n # (MW) ($/MW) ')
fd.write('\n---- -------- --------')
for k in range(nrz):
iz = find(r['zones'][k, :]) ## gens in zone k
fd.write('\n%3d%10.2f%10.2f' % (k, sum(results['reserves']['R'][iz]),
results['lin']['mu']['l']['Rreq'][k] / results['baseMVA']))
fd.write('\n')
fd.write('\n================================================================================')
fd.write('\n| Reserve Limits |')
fd.write('\n================================================================================')
fd.write('\n Gen Bus Status Rmin mu Rmin Reserves Rmax Rmax mu Pmax mu ')
fd.write('\n # # ($/MW) (MW) (MW) (MW) ($/MW) ($/MW) ')
fd.write('\n---- ----- ------ -------- -------- -------- -------- -------- --------')
for k in r['igr']:
fd.write('\n%3d %6d %2d ' % (k, results['gen'][k, GEN_BUS], results['gen'][k, GEN_STATUS]))
if (results['gen'][k, GEN_STATUS] > 0) & (results['reserves']['mu']['l'][k] > 1e-6):
fd.write('%10.2f' % results['reserves']['mu']['l'][k])
else:
fd.write(' - ')
fd.write('%10.2f' % results['reserves']['Rmin'][k])
if (results['gen'][k, GEN_STATUS] > 0) & (abs(results['reserves']['R'][k]) > 1e-6):
fd.write('%10.2f' % results['reserves']['R'][k])
else:
fd.write(' - ')
fd.write('%10.2f' % results['reserves']['Rmax'][k])
if (results['gen'][k, GEN_STATUS] > 0) & (results['reserves']['mu']['u'][k] > 1e-6):
fd.write('%10.2f' % results['reserves']['mu']['u'][k])
else:
fd.write(' - ')
if (results['gen'][k, GEN_STATUS] > 0) & (results['reserves']['mu']['Pmax'][k] > 1e-6):
fd.write('%10.2f' % results['reserves']['mu']['Pmax'][k])
else:
fd.write(' - ')
fd.write('\n --------')
fd.write('\n Total:%10.2f' % sum(results['reserves']['R'][r['igr']]))
fd.write('\n')
return results
0
Example 44
Project: PYPOWER Source File: total_load.py
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
0
Example 45
Project: PYPOWER Source File: totcost.py
def totcost(gencost, Pg):
"""Computes total cost for generators at given output level.
Computes total cost for generators given a matrix in gencost format and
a column vector or matrix of generation levels. The return value has the
same dimensions as PG. Each row of C{gencost} is used to evaluate the
cost at the points specified in the corresponding row of C{Pg}.
@author: Ray Zimmerman (PSERC Cornell)
@author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
Autonoma de Manizales)
"""
ng, m = gencost.shape
totalcost = zeros(ng)
if len(gencost) > 0:
ipwl = find(gencost[:, MODEL] == PW_LINEAR)
ipol = find(gencost[:, MODEL] == POLYNOMIAL)
if len(ipwl) > 0:
p = gencost[:, COST:(m-1):2]
c = gencost[:, (COST+1):m:2]
for i in ipwl:
ncost = gencost[i, NCOST]
for k in arange(ncost - 1):
p1, p2 = p[i, k], p[i, k+1]
c1, c2 = c[i, k], c[i, k+1]
m = (c2 - c1) / (p2 - p1)
b = c1 - m * p1
Pgen = Pg[i]
if Pgen < p2:
totalcost[i] = m * Pgen + b
break
totalcost[i] = m * Pgen + b
if len(ipol) > 0:
totalcost[ipol] = polycost(gencost[ipol, :], Pg[ipol])
return totalcost
0
Example 46
Project: PYPOWER Source File: uopf.py
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)
"""
##----- 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