Пример #1
0
def poly2pwl(polycost, Pmin, Pmax, npts):
    """Converts polynomial cost variable to piecewise linear.

    Converts the polynomial cost variable C{polycost} into a piece-wise linear
    cost by evaluating at zero and then at C{npts} evenly spaced points between
    C{Pmin} and C{Pmax}. If C{Pmin <= 0} (such as for reactive power, where
    C{P} really means C{Q}) it just uses C{npts} evenly spaced points between
    C{Pmin} and C{Pmax}.
    """
    pwlcost = polycost
    ## size of piece being changed
    m, n = polycost.shape
    ## change cost model
    pwlcost[:, MODEL]  = PW_LINEAR * ones(m)
    ## zero out old data
    pwlcost[:, COST:COST + n] = zeros(pwlcost[:, COST:COST + n].shape)
    ## change number of data points
    pwlcost[:, NCOST]  = npts * ones(m)

    for i in range(m):
        if Pmin[i] == 0:
            step = (Pmax[i] - Pmin[i]) / (npts - 1)
            xx = range(Pmin[i], step, Pmax[i])
        elif Pmin[i] > 0:
            step = (Pmax[i] - Pmin[i]) / (npts - 2)
            xx = r_[0, range(Pmin[i], step, Pmax[i])]
        elif Pmin[i] < 0 & Pmax[i] > 0:        ## for when P really means Q
            step = (Pmax[i] - Pmin[i]) / (npts - 1)
            xx = range(Pmin[i], step, Pmax[i])
        yy = totcost(polycost[i, :], xx)
        pwlcost[i,      COST:2:(COST + 2*(npts-1)    )] = xx
        pwlcost[i,  (COST+1):2:(COST + 2*(npts-1) + 1)] = yy

    return pwlcost
def t_totcost(quiet=False):
    """Tests for code in C{totcost}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    n_tests = 22

    t_begin(n_tests, quiet)

    ## generator cost data
    #    1    startup    shutdown    n    x1    y1    ...    xn    yn
    #    2    startup    shutdown    n    c(n-1)    ...    c0
    gencost = array([
        [2, 0, 0, 3,   0.01,   0.1,    1,     0,    0,     0,  0,    0],
        [2, 0, 0, 5,   0.0006, 0.005,  0.04,  0.3,  2,     0,  0,    0],
        [1, 0, 0, 4,   0,      0,     10,   200,   20,   600, 30, 1200],
        [1, 0, 0, 4, -30,  -2400,    -20, -1800,  -10, -1000,  0,    0]
    ])

    t = 'totcost - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0])), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0])), [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0])), [1.24, 2, 0, 0], 8, t)

    t = 'totcost - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0])), [1, 2,      0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0])), [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0])), [1, 2.8096, 0, 0], 8, t)

    t = 'totcost - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, -10, 0 ])), [1, 2, -200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 5, 0 ])),   [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0])),   [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0])),   [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0])),   [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0])),   [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0])),   [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0])),   [1, 2, 1500, 0], 8, t)

    t = 'totcost - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, 10 ])), [1, 2, 0, 1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -5 ])), [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10])), [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15])), [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20])), [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25])), [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30])), [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35])), [1, 2, 0, -2700], 8, t)

    t_end()
Пример #3
0
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 = list(range(vv["i1"]["Pg"], vv["iN"]["Pg"]))
    iQg = list(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' %
                       (list(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[list(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, (list(range(nw)), list(range(nw)))), (nw, nw)) * N

    return f, df, d2f
Пример #4
0
def t_totcost(quiet=False):
    """Tests for code in C{totcost}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    n_tests = 22

    t_begin(n_tests, quiet)

    ## generator cost data
    #    1    startup    shutdown    n    x1    y1    ...    xn    yn
    #    2    startup    shutdown    n    c(n-1)    ...    c0
    gencost = array([[2, 0, 0, 3, 0.01, 0.1, 1, 0, 0, 0, 0, 0],
                     [2, 0, 0, 5, 0.0006, 0.005, 0.04, 0.3, 2, 0, 0, 0],
                     [1, 0, 0, 4, 0, 0, 10, 200, 20, 600, 30, 1200],
                     [1, 0, 0, 4, -30, -2400, -20, -1800, -10, -1000, 0, 0]])

    t = 'totcost - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0])), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0])), [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0])), [1.24, 2, 0, 0], 8, t)

    t = 'totcost - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0])), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0])), [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0])), [1, 2.8096, 0, 0], 8, t)

    t = 'totcost - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, -10, 0])), [1, 2, -200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 5, 0])), [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0])), [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0])), [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0])), [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0])), [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0])), [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0])), [1, 2, 1500, 0], 8, t)

    t = 'totcost - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, 10])), [1, 2, 0, 1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -5])), [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10])), [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15])), [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20])), [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25])), [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30])), [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35])), [1, 2, 0, -2700], 8, t)

    t_end()
Пример #5
0
def uopf(*args):
    """Solves combined unit decommitment / optimal power flow.

    Solves a combined unit decommitment and optimal power flow for a single
    time period. Uses an algorithm similar to dynamic programming. It proceeds
    through a sequence of stages, where stage C{N} has C{N} generators shut
    down, starting with C{N=0}. In each stage, it forms a list of candidates
    (gens at their C{Pmin} limits) and computes the cost with each one of them
    shut down. It selects the least cost case as the starting point for the
    next stage, continuing until there are no more candidates to be shut down
    or no more improvement can be gained by shutting something down.
    If C{verbose} in ppopt (see L{ppoption} is C{true}, it prints progress
    info, if it is > 1 it prints the output of each individual opf.

    @see: L{opf}, L{runuopf}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ##----- initialization -----
    t0 = time()  ## start timer

    ## process input arguments
    ppc, ppopt = opf_args2(*args)

    ## options
    verbose = ppopt["VERBOSE"]
    if verbose:  ## turn down verbosity one level for calls to opf
        ppopt = ppoption(ppopt, VERBOSE=verbose - 1)

    ##-----  do combined unit commitment/optimal power flow  -----

    ## check for sum(Pmin) > total load, decommit as necessary
    on = find((ppc["gen"][:, GEN_STATUS] > 0)
              & ~isload(ppc["gen"]))  ## gens in service
    onld = find((ppc["gen"][:, GEN_STATUS] > 0)
                & isload(ppc["gen"]))  ## disp loads in serv
    load_capacity = sum(ppc["bus"][:, PD]) - sum(
        ppc["gen"][onld, PMIN])  ## total load capacity
    Pmin = ppc["gen"][on, PMIN]
    while sum(Pmin) > load_capacity:
        ## shut down most expensive unit
        avgPmincost = totcost(ppc["gencost"][on, :], Pmin) / Pmin
        _, i = fairmax(avgPmincost)  ## pick one with max avg cost at Pmin
        i = on[i]  ## convert to generator index

        if verbose:
            print(
                'Shutting down generator %d so all Pmin limits can be satisfied.\n'
                % i)

        ## set generation to zero
        ppc["gen"][i, [PG, QG, GEN_STATUS]] = 0

        ## update minimum gen capacity
        on = find((ppc["gen"][:, GEN_STATUS] > 0)
                  & ~isload(ppc["gen"]))  ## gens in service
        Pmin = ppc["gen"][on, PMIN]

    ## run initial opf
    results = opf(ppc, ppopt)

    ## best case so far
    results1 = deepcopy(results)

    ## best case for this stage (ie. with n gens shut down, n=0,1,2 ...)
    results0 = deepcopy(results1)
    ppc["bus"] = results0["bus"].copy(
    )  ## use these V as starting point for OPF

    while True:
        ## get candidates for shutdown
        candidates = find((results0["gen"][:, MU_PMIN] > 0)
                          & (results0["gen"][:, PMIN] > 0))
        if len(candidates) == 0:
            break

        ## do not check for further decommitment unless we
        ##  see something better during this stage
        done = True

        for k in candidates:
            ## start with best for this stage
            ppc["gen"] = results0["gen"].copy()

            ## shut down gen k
            ppc["gen"][k, [PG, QG, GEN_STATUS]] = 0

            ## run opf
            results = opf(ppc, ppopt)

            ## something better?
            if results['success'] and (results["f"] < results1["f"]):
                results1 = deepcopy(results)
                k1 = k
                done = False  ## make sure we check for further decommitment

        if done:
            ## decommits at this stage did not help, so let's quit
            break
        else:
            ## shutting something else down helps, so let's keep going
            if verbose:
                print('Shutting down generator %d.\n' % k1)

            results0 = deepcopy(results1)
            ppc["bus"] = results0["bus"].copy(
            )  ## use these V as starting point for OPF

    ## compute elapsed time
    et = time() - t0

    ## finish preparing output
    results0['et'] = et

    return results0
Пример #6
0
def t_modcost(quiet=False):
    """Tests for code in C{modcost}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    n_tests = 80

    t_begin(n_tests, quiet)

    ## generator cost data
    #    1    startup    shutdown    n    x1    y1    ...    xn    yn
    #    2    startup    shutdown    n    c(n-1)    ...    c0
    gencost0 = array([
        [2, 0, 0, 3, 0.01,   0.1,   1,    0,    0,  0,      0,    0],
        [2, 0, 0, 5, 0.0006, 0.005, 0.04, 0.3,  2,  0,      0,    0],
        [1, 0, 0, 4, 0,      0,     10,   200,  20, 600,   30, 1200],
        [1, 0, 0, 4, -30,   -2400, -20, -1800, -10, -1000,  0,    0]
    ])

    gencost = modcost(gencost0, 5, 'SCALE_F')

    ##-----  POLYSHIFT  -----
    t = 'modcost SCALE_F - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0])) / 5, [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0])) / 5, [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0])) / 5, [1.24, 2, 0, 0], 8, t)

    t = 'modcost SCALE_F - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0])) / 5, [1, 2,      0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0])) / 5, [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0])) / 5, [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SCALE_F - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0 ])) / 5, [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0])) / 5, [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0])) / 5, [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0])) / 5, [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0])) / 5, [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0])) / 5, [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0])) / 5, [1, 2, 1500, 0], 8, t)

    t = 'modcost SCALE_F - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5 ])) / 5, [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10])) / 5, [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15])) / 5, [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20])) / 5, [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25])) / 5, [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30])) / 5, [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35])) / 5, [1, 2, 0, -2700], 8, t)


    gencost = modcost(gencost0, 2, 'SCALE_X')

    t = 'modcost SCALE_X - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0]) * 2), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0]) * 2), [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0]) * 2), [1.24, 2, 0, 0], 8, t)

    t = 'modcost SCALE_X - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0]) * 2), [1, 2,      0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0]) * 2), [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0]) * 2), [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SCALE_X - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0 ]) * 2), [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0]) * 2), [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0]) * 2), [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0]) * 2), [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0]) * 2), [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0]) * 2), [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0]) * 2), [1, 2, 1500, 0], 8, t)

    t = 'modcost SCALE_X - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5 ]) * 2), [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10]) * 2), [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15]) * 2), [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20]) * 2), [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25]) * 2), [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30]) * 2), [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35]) * 2), [1, 2, 0, -2700], 8, t)


    gencost = modcost(gencost0, 3, 'SHIFT_F')

    t = 'modcost SHIFT_F - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0])) - 3, [1,    2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0])) - 3, [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0])) - 3, [1.24, 2, 0, 0], 8, t)

    t = 'modcost SHIFT_F - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0])) - 3, [1, 2,      0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0])) - 3, [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0])) - 3, [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SHIFT_F - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0 ])) - 3, [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0])) - 3, [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0])) - 3, [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0])) - 3, [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0])) - 3, [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0])) - 3, [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0])) - 3, [1, 2, 1500, 0], 8, t)

    t = 'modcost SHIFT_F - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5 ])) - 3, [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10])) - 3, [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15])) - 3, [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20])) - 3, [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25])) - 3, [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30])) - 3, [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35])) - 3, [1, 2, 0, -2700], 8, t)


    gencost = modcost(gencost0, -4, 'SHIFT_X')

    t = 'modcost SHIFT_X - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0]) - 4), [1,    2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0]) - 4), [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0]) - 4), [1.24, 2, 0, 0], 8, t)

    t = 'modcost SHIFT_X - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0]) - 4), [1, 2,      0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0]) - 4), [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0]) - 4), [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SHIFT_X - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0 ]) - 4), [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0]) - 4), [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0]) - 4), [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0]) - 4), [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0]) - 4), [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0]) - 4), [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0]) - 4), [1, 2, 1500, 0], 8, t)

    t = 'modcost SHIFT_X - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5 ]) - 4), [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10]) - 4), [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15]) - 4), [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20]) - 4), [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25]) - 4), [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30]) - 4), [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35]) - 4), [1, 2, 0, -2700], 8, t)

    t_end()
Пример #7
0
def uopf(*args):
    """Solves combined unit decommitment / optimal power flow.

    Solves a combined unit decommitment and optimal power flow for a single
    time period. Uses an algorithm similar to dynamic programming. It proceeds
    through a sequence of stages, where stage C{N} has C{N} generators shut
    down, starting with C{N=0}. In each stage, it forms a list of candidates
    (gens at their C{Pmin} limits) and computes the cost with each one of them
    shut down. It selects the least cost case as the starting point for the
    next stage, continuing until there are no more candidates to be shut down
    or no more improvement can be gained by shutting something down.
    If C{verbose} in ppopt (see L{ppoption} is C{true}, it prints progress
    info, if it is > 1 it prints the output of each individual opf.

    @see: L{opf}, L{runuopf}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ##----- initialization -----
    t0 = time()                                 ## start timer

    ## process input arguments
    ppc, ppopt = opf_args2(*args)

    ## options
    verbose = ppopt["VERBOSE"]
    if verbose:      ## turn down verbosity one level for calls to opf
        ppopt = ppoption(ppopt, VERBOSE=verbose - 1)

    ##-----  do combined unit commitment/optimal power flow  -----

    ## check for sum(Pmin) > total load, decommit as necessary
    on   = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) )   ## gens in service
    onld = find( (ppc["gen"][:, GEN_STATUS] > 0) &  isload(ppc["gen"]) )   ## disp loads in serv
    load_capacity = sum(ppc["bus"][:, PD]) - sum(ppc["gen"][onld, PMIN])   ## total load capacity
    Pmin = ppc["gen"][on, PMIN]
    while sum(Pmin) > load_capacity:
        ## shut down most expensive unit
        avgPmincost = totcost(ppc["gencost"][on, :], Pmin) / Pmin
        _, i = fairmax(avgPmincost)   ## pick one with max avg cost at Pmin
        i = on[i]                     ## convert to generator index

        if verbose:
            print('Shutting down generator %d so all Pmin limits can be satisfied.\n' % i)

        ## set generation to zero
        ppc["gen"][i, [PG, QG, GEN_STATUS]] = 0

        ## update minimum gen capacity
        on  = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) )   ## gens in service
        Pmin = ppc["gen"][on, PMIN]

    ## run initial opf
    results = opf(ppc, ppopt)

    ## best case so far
    results1 = deepcopy(results)

    ## best case for this stage (ie. with n gens shut down, n=0,1,2 ...)
    results0 = deepcopy(results1)
    ppc["bus"] = results0["bus"].copy()     ## use these V as starting point for OPF

    while True:
        ## get candidates for shutdown
        candidates = find((results0["gen"][:, MU_PMIN] > 0) & (results0["gen"][:, PMIN] > 0))
        if len(candidates) == 0:
            break

        ## do not check for further decommitment unless we
        ##  see something better during this stage
        done = True

        for k in candidates:
            ## start with best for this stage
            ppc["gen"] = results0["gen"].copy()

            ## shut down gen k
            ppc["gen"][k, [PG, QG, GEN_STATUS]] = 0

            ## run opf
            results = opf(ppc, ppopt)

            ## something better?
            if results['success'] and (results["f"] < results1["f"]):
                results1 = deepcopy(results)
                k1 = k
                done = False   ## make sure we check for further decommitment

        if done:
            ## decommits at this stage did not help, so let's quit
            break
        else:
            ## shutting something else down helps, so let's keep going
            if verbose:
                print('Shutting down generator %d.\n' % k1)

            results0 = deepcopy(results1)
            ppc["bus"] = results0["bus"].copy()     ## use these V as starting point for OPF

    ## compute elapsed time
    et = time() - t0

    ## finish preparing output
    results0['et'] = et

    return results0
Пример #8
0
def t_modcost(quiet=False):
    """Tests for code in C{modcost}.

    @author: Ray Zimmerman (PSERC Cornell)
    """
    n_tests = 80

    t_begin(n_tests, quiet)

    ## generator cost data
    #    1    startup    shutdown    n    x1    y1    ...    xn    yn
    #    2    startup    shutdown    n    c(n-1)    ...    c0
    gencost0 = array([[2, 0, 0, 3, 0.01, 0.1, 1, 0, 0, 0, 0, 0],
                      [2, 0, 0, 5, 0.0006, 0.005, 0.04, 0.3, 2, 0, 0, 0],
                      [1, 0, 0, 4, 0, 0, 10, 200, 20, 600, 30, 1200],
                      [1, 0, 0, 4, -30, -2400, -20, -1800, -10, -1000, 0, 0]])

    gencost = modcost(gencost0, 5, 'SCALE_F')

    ##-----  POLYSHIFT  -----
    t = 'modcost SCALE_F - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0])) / 5, [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0])) / 5, [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0])) / 5, [1.24, 2, 0, 0], 8, t)

    t = 'modcost SCALE_F - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0])) / 5, [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0])) / 5, [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0])) / 5, [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SCALE_F - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0])) / 5, [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0])) / 5, [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0])) / 5, [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0])) / 5, [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0])) / 5, [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0])) / 5, [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0])) / 5, [1, 2, 1500, 0], 8, t)

    t = 'modcost SCALE_F - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5])) / 5, [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10])) / 5, [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15])) / 5, [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20])) / 5, [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25])) / 5, [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30])) / 5, [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35])) / 5, [1, 2, 0, -2700], 8, t)

    gencost = modcost(gencost0, 2, 'SCALE_X')

    t = 'modcost SCALE_X - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0]) * 2), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0]) * 2), [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0]) * 2), [1.24, 2, 0, 0], 8, t)

    t = 'modcost SCALE_X - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0]) * 2), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0]) * 2), [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0]) * 2), [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SCALE_X - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0]) * 2), [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0]) * 2), [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0]) * 2), [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0]) * 2), [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0]) * 2), [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0]) * 2), [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0]) * 2), [1, 2, 1500, 0], 8, t)

    t = 'modcost SCALE_X - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5]) * 2), [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10]) * 2), [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15]) * 2), [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20]) * 2), [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25]) * 2), [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30]) * 2), [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35]) * 2), [1, 2, 0, -2700], 8, t)

    gencost = modcost(gencost0, 3, 'SHIFT_F')

    t = 'modcost SHIFT_F - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0])) - 3, [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0])) - 3, [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0])) - 3, [1.24, 2, 0, 0], 8, t)

    t = 'modcost SHIFT_F - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0])) - 3, [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0])) - 3, [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0])) - 3, [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SHIFT_F - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0])) - 3, [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0])) - 3, [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0])) - 3, [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0])) - 3, [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0])) - 3, [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0])) - 3, [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0])) - 3, [1, 2, 1500, 0], 8, t)

    t = 'modcost SHIFT_F - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5])) - 3, [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10])) - 3, [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15])) - 3, [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20])) - 3, [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25])) - 3, [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30])) - 3, [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35])) - 3, [1, 2, 0, -2700], 8, t)

    gencost = modcost(gencost0, -4, 'SHIFT_X')

    t = 'modcost SHIFT_X - quadratic'
    t_is(totcost(gencost, array([0, 0, 0, 0]) - 4), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([1, 0, 0, 0]) - 4), [1.11, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([2, 0, 0, 0]) - 4), [1.24, 2, 0, 0], 8, t)

    t = 'modcost SHIFT_X - 4th order polynomial'
    t_is(totcost(gencost, array([0, 0, 0, 0]) - 4), [1, 2, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 1, 0, 0]) - 4), [1, 2.3456, 0, 0], 8, t)
    t_is(totcost(gencost, array([0, 2, 0, 0]) - 4), [1, 2.8096, 0, 0], 8, t)

    t = 'modcost SHIFT_X - pwl (gen)'
    t_is(totcost(gencost, array([0, 0, 5, 0]) - 4), [1, 2, 100, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 10, 0]) - 4), [1, 2, 200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 15, 0]) - 4), [1, 2, 400, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 20, 0]) - 4), [1, 2, 600, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 25, 0]) - 4), [1, 2, 900, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 30, 0]) - 4), [1, 2, 1200, 0], 8, t)
    t_is(totcost(gencost, array([0, 0, 35, 0]) - 4), [1, 2, 1500, 0], 8, t)

    t = 'modcost SHIFT_X - pwl (load)'
    t_is(totcost(gencost, array([0, 0, 0, -5]) - 4), [1, 2, 0, -500], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -10]) - 4), [1, 2, 0, -1000], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -15]) - 4), [1, 2, 0, -1400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -20]) - 4), [1, 2, 0, -1800], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -25]) - 4), [1, 2, 0, -2100], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -30]) - 4), [1, 2, 0, -2400], 8, t)
    t_is(totcost(gencost, array([0, 0, 0, -35]) - 4), [1, 2, 0, -2700], 8, t)

    t_end()
Пример #9
0
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)
    @author: Richard Lincoln
    """
    ##----- 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