numpy.find

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 7

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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)

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

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

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

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

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

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

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()

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()

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()

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()

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

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()

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()

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

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

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

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

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

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

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

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

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

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

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

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