Ejemplo n.º 1
0
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
Ejemplo n.º 2
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
def total_load(bus, gen=None, load_zone=None, which_type=None):
    """Returns vector of total load in each load zone.

    @param bus: standard C{bus} matrix with C{nb} rows, where the fixed active
    and reactive loads are specified in columns C{PD} and C{QD}

    @param gen: (optional) standard C{gen} matrix with C{ng} rows, where the
    dispatchable loads are specified by columns C{PG}, C{QG}, C{PMIN},
    C{QMIN} and C{QMAX} (in rows for which C{isload(GEN)} returns C{True}).
    If C{gen} is empty, it assumes there are no dispatchable loads.

    @param load_zone: (optional) C{nb} element vector where the value of
    each element is either zero or the index of the load zone
    to which the corresponding bus belongs. If C{load_zone(b) = k}
    then the loads at bus C{b} will added to the values of C{Pd[k]} and
    C{Qd[k]}. If C{load_zone} is empty, the default is defined as the areas
    specified in the C{bus} matrix, i.e. C{load_zone =  bus[:, BUS_AREA]}
    and load will have dimension C{= max(bus[:, BUS_AREA])}. If
    C{load_zone = 'all'}, the result is a scalar with the total system
    load.

    @param which_type: (default is 'BOTH' if C{gen} is provided, else 'FIXED')
        - 'FIXED'        : sum only fixed loads
        - 'DISPATCHABLE' : sum only dispatchable loads
        - 'BOTH'         : sum both fixed and dispatchable loads

    @see: L{scale_load}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    nb = bus.shape[0]       ## number of buses

    if gen is None:
        gen = array([])
    if load_zone is None:
        load_zone = array([], int)

    ## fill out and check which_type
    if len(gen) == 0:
        which_type = 'FIXED'

    if (which_type == None) and (len(gen) > 0):
        which_type = 'BOTH'     ## 'FIXED', 'DISPATCHABLE' or 'BOTH'

    if (which_type[0] != 'F') and (which_type[0] != 'D') and (which_type[0] != 'B'):
        stderr.write("total_load: which_type should be 'FIXED, 'DISPATCHABLE or 'BOTH'\n")

    want_Q      = True
    want_fixed  = (which_type[0] == 'B') | (which_type[0] == 'F')
    want_disp   = (which_type[0] == 'B') | (which_type[0] == 'D')

    ## initialize load_zone
    if isinstance(load_zone, basestring) and (load_zone == 'all'):
        load_zone = ones(nb, int)                  ## make a single zone of all buses
    elif len(load_zone) == 0:
        load_zone = bus[:, BUS_AREA].astype(int)   ## use areas defined in bus data as zones

    nz = max(load_zone)    ## number of load zones

    ## fixed load at each bus, & initialize dispatchable
    if want_fixed:
        Pdf = bus[:, PD]       ## real power
        if want_Q:
            Qdf = bus[:, QD]   ## reactive power
    else:
        Pdf = zeros(nb)     ## real power
        if want_Q:
            Qdf = zeros(nb) ## reactive power

    ## dispatchable load at each bus
    if want_disp:            ## need dispatchable
        ng = gen.shape[0]
        is_ld = isload(gen) and (gen[:, GEN_STATUS] > 0)
        ld = find(is_ld)

        ## create map of external bus numbers to bus indices
        i2e = bus[:, BUS_I].astype(int)
        e2i = zeros(max(i2e) + 1)
        e2i[i2e] = arange(nb)

        gbus = gen[:, GEN_BUS].astype(int)
        Cld = sparse((is_ld, (e2i[gbus], arange(ng))), (nb, ng))
        Pdd = -Cld * gen[:, PMIN]      ## real power
        if want_Q:
            Q = zeros(ng)
            Q[ld] = (gen[ld, QMIN] == 0) * gen[ld, QMAX] + \
                    (gen[ld, QMAX] == 0) * gen[ld, QMIN]
            Qdd = -Cld * Q             ## reactive power
    else:
        Pdd = zeros(nb)
        if want_Q:
            Qdd = zeros(nb)

    ## compute load sums
    Pd = zeros(nz)
    if want_Q:
        Qd = zeros(nz)

    for k in range(1, nz + 1):
        idx = find(load_zone == k)
        Pd[k - 1] = sum(Pdf[idx]) + sum(Pdd[idx])
        if want_Q:
            Qd[k - 1] = sum(Qdf[idx]) + sum(Qdd[idx])

    return Pd, Qd
Ejemplo n.º 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
Ejemplo n.º 8
0
def t_runmarket(quiet=False):
    """Tests for code in C{runmkt}, C{smartmkt} and C{auction}.

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

    t_begin(n_tests, quiet)

    try:
        from pypower.extras.smartmarket import runmarket
    except ImportError:
        t_skip(n_tests, 'smartmarket code not available')
        t_end;
        return

    ppc = loadcase('t_auction_case')

    ppopt = ppoption(OPF_ALG=560, OUT_ALL_LIM=1,
                     OUT_BRANCH=0, OUT_SYS_SUM=0)
    ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=1)
    #ppopt = ppoption(ppopt, OUT_GEN=1, OUT_BRANCH=0, OUT_SYS_SUM=0)

    offers = {'P': {}, 'Q': {}}
    bids = {'P': {}, 'Q': {}}

    offers['P']['qty'] = array([
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24]
    ])
    offers['P']['prc'] = array([
        [20, 50, 60],
        [20, 40, 70],
        [20, 42, 80],
        [20, 44, 90],
        [20, 46, 75],
        [20, 48, 60]
    ])
    bids['P']['qty'] = array([
        [10, 10, 10],
        [10, 10, 10],
        [10, 10, 10]
    ])
    bids['P']['prc'] = array([
        [100, 70, 60],
#         [100, 64.3, 20],
#         [100, 30.64545, 0],
        [100, 50, 20],
        [100, 60, 50]
    ])

    offers['Q']['qty'] = [ 60, 60, 60, 60, 60, 60, 0, 0, 0 ]
    offers['Q']['prc'] = [ 0, 0, 0, 0, 0, 3, 0, 0, 0 ]
    bids.Q['qty'] = [ 15, 15, 15, 15, 15, 15, 15, 12, 7.5 ]
#     bids.Q['prc'] = [ 0, 0, 0, 0, 0, 0, 0, 83.9056, 0 ]
    bids.Q['prc'] = [ 0, 0, 0, 0, 0, 0, 0, 20, 0 ]

    t = 'marginal Q offer, marginal PQ bid, auction_type = 5'
    mkt = {'auction_type': 5,
                      't': [],
                     'u0': [],
                    'lim': []}
    r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt)
    co5 = co.copy()
    cb5 = cb.copy()

#     [ co['P']['qty'] co['P']['prc'] ]
#     [ cb['P']['qty'] cb['P']['prc'] ]
#     [ co['Q']['qty'] co['Q']['prc'] ]
#     [ cb['Q']['qty'] cb['Q']['prc'] ]

    i2e = r['bus'][:, BUS_I]
    e2i = sparse((max(i2e), 1))
    e2i[i2e] = range(r['bus'].size)
    G = find( isload(r['gen']) == 0 )   ## real generators
    L = find( isload(r['gen']) )        ## dispatchable loads
    Gbus = e2i[r['gen'][G, GEN_BUS]]
    Lbus = e2i[r['gen'][L, GEN_BUS]]

    t_is( co['P']['qty'], ones((6, 1)) * [12, 24, 0], 2, [t, ' : gen P quantities'] )
    t_is( co['P']['prc'][0, :], 50.1578, 3, [t, ' : gen 1 P prices'] )
    t_is( cb['P']['qty'], [[10, 10, 10], [10, 0.196, 0], [10, 10, 0]], 2, [t, ' : load P quantities'] )
    t_is( cb['P']['prc'][1, :], 56.9853, 4, [t, ' : load 2 P price'] )
    t_is( co['P']['prc'][:, 0], r['bus'][Gbus, LAM_P], 8, [t, ' : gen P prices'] )
    t_is( cb['P']['prc'][:, 0], r['bus'][Lbus, LAM_P], 8, [t, ' : load P prices'] )

    t_is( co['Q']['qty'], [4.2722, 11.3723, 14.1472, 22.8939, 36.7886, 12.3375, 0, 0, 0], 2, [t, ' : Q offer quantities'] )
    t_is( co['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4, [t, ' : Q offer prices'] )
    t_is( cb['Q']['qty'], [0, 0, 0, 0, 0, 0, 15, 4.0785, 5], 2, [t, ' : Q bid quantities'] )
    t_is( cb['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4, [t, ' : Q bid prices'] )
    t_is( co['Q']['prc'], r['bus'][[Gbus, Lbus], LAM_Q], 8, [t, ' : Q offer prices'] )
    t_is( cb['Q']['prc'], co['Q']['prc'], 8, [t, ' : Q bid prices'] )

    t = 'marginal Q offer, marginal PQ bid, auction_type = 0'
    mkt['auction_type'] = 0
    r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt)
    t_is( co['P']['qty'], co5['P']['qty'], 8, [t, ' : gen P quantities'] )
    t_is( cb['P']['qty'], cb5['P']['qty'], 8, [t, ' : load P quantities'] )
    t_is( co['P']['prc'], offers['P']['prc'], 8, [t, ' : gen P prices'] )
    t_is( cb['P']['prc'], bids['P']['prc'], 8, [t, ' : load P prices'] )

    t_is( co['Q']['qty'], co5['Q']['qty'], 8, [t, ' : gen Q quantities'] )
    t_is( cb['Q']['qty'], cb5['Q']['qty'], 8, [t, ' : load Q quantities'] )
    t_is( co['Q']['prc'], offers['Q']['prc'], 8, [t, ' : gen Q prices'] )
    t_is( cb['Q']['prc'], bids['Q']['prc'], 8, [t, ' : load Q prices'] )


    t_end
def t_off2case(quiet=False):
    """Tests for code in C{off2case}.

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

    t_begin(n_tests, quiet)

    ## generator data
    #    bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf
    gen0 = array([
        [1,   10,   0,  60, -15, 1, 100, 1, 60, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [2,   10,   0,  60, -15, 1, 100, 1, 60, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [7,  -30, -15,   0, -15, 1, 100, 1, 0, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [13,  10,   0,  60, -15, 1, 100, 1, 60, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [30, -30, 7.5, 7.5,   0, 1, 100, 1, 0, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    ], float)
    ## generator cost data
    #    1    startup    shutdown    n    x1    y1    ...    xn    yn
    #    2    startup    shutdown    n    c(n-1)    ...    c0
    gencost0 = array([
        [1, 0,   0, 4,   0, 0,  12, 240,   36, 1200, 60, 2400],
        [1, 100, 0, 4,   0, 0,  12, 240,   36, 1200, 60, 2400],
        [1, 0,   0, 4, -30, 0, -20, 1000, -10, 2000,  0, 3000],
        [1, 0,   0, 4,   0, 0,  12, 240,   36, 1200, 60, 2400],
        [1, 0,  50, 4, -30, 0, -20, 1000, -10, 2000,  0, 3000]
    ], float)

    try:
        from pypower.extras.smartmarket import off2case
    except ImportError:
        t_skip(n_tests, 'smartmarket code not available')
        return

    t = 'isload()'
    t_is(isload(gen0), array([0, 0, 1, 0, 1], bool), 8, t)

    G = find( ~isload(gen0) )
    L = find(  isload(gen0) )
    nGL = len(G) + len(L)

    t = 'P offers only';
    offers = {'P': {}}
    offers['P']['qty'] = array([[25], [26], [27]], float)
    offers['P']['prc'] = array([[10], [50], [100]], float)
    gen, gencost = off2case(gen0, gencost0, offers)

    gen1 = gen0.copy()
    gen1[G, PMAX] = offers['P']['qty'].flatten()
    gen1[L, GEN_STATUS] = 0
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0.copy()
    gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 25,  250],
        [2, 0, 0, 26, 1300],
        [2, 0, 0, 27, 2700],
    ]), zeros((3, 4))]

    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    offers['P']['qty'] = array([[25], [26], [0], [27],  [0]], float)
    offers['P']['prc'] = array([[10], [50], [0], [100], [0]], float)
    gen, gencost = off2case(gen0, gencost0, offers)
    t_is( gen, gen1, 8, [t, ' (all rows in offer) - gen'] )
    t_is( gencost, gencost1, 8, [t, ' (all rows in offer) - gencost'] )

    t = 'P offers only (GEN_STATUS=0 for 0 qty offer)';
    offers['P']['qty'] = array([ [0], [26],  [27]], float)
    offers['P']['prc'] = array([[10], [50], [100]], float)
    gen, gencost = off2case(gen0, gencost0, offers)

    gen1 = gen0.copy()
    gen1[G[1:3], PMAX] = offers['P']['qty'].flatten()[1:3]
    gen1[G[0], GEN_STATUS] = 0
    gen1[L, GEN_STATUS] = 0
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0.copy()
    gencost1[ix_(G[1:3], range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 26, 1300],
        [2, 0, 0, 27, 2700]
    ]), zeros((2, 4))]

    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers, lim[\'P\'][\'max_offer\']';
    offers['P']['qty'] = array([[25], [26], [27]], float)
    offers['P']['prc'] = array([[10], [50], [100]], float)
    lim = {'P': {'max_offer': 75}}
    gen, gencost = off2case(gen0, gencost0, offers, lim=lim)

    gen1 = gen0.copy()
    gen1[G[:2], PMAX] = offers['P']['qty'].flatten()[:2, :]
    gen1[r_[G[2], L], GEN_STATUS] = 0
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0.copy()
    gencost1[ix_(G[:2], range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 25,  250],
        [2, 0, 0, 26, 1300]
    ]), zeros((2, 4))]
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers & P bids';
    bids = {'P': {'qty': array([ [20], [28]], float),
                  'prc': array([[100], [10]], float)}}
    gen, gencost = off2case(gen0, gencost0, offers, bids)

    gen1 = gen0.copy()
    gen1[G, PMAX] = offers['P']['qty']
    gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([
        [-20, -10, 0],
        [-28,   0, 7]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :8].copy()
    gencost1[ix_(G, range(NCOST, NCOST + 4))] = array([
        [2, 0, 0, 25,  250],
        [2, 0, 0, 26, 1300],
        [2, 0, 0, 27, 2700]
    ])
    gencost1[ix_(L, range(NCOST, NCOST + 4))] = array([
        [2, -20, -2000, 0, 0],
        [2, -28,  -280, 0, 0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers & P bids (all rows in bid)';
    bids['P']['qty'] = array([[0], [0],  [20], [0], [28]], float)
    bids['P']['prc'] = array([[0], [0], [100], [0], [10]], float)
    gen, gencost = off2case(gen0, gencost0, offers, bids)

    t_is( gen, gen1, 8, [t, ' - gen'] )
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers & P bids (GEN_STATUS=0 for 0 qty bid)';
    bids['P']['qty'] = array([  [0], [28]], float)
    bids['P']['prc'] = array([[100], [10]], float)
    gen, gencost = off2case(gen0, gencost0, offers, bids)

    gen1 = gen0.copy()
    gen1[G, PMAX] = offers['P']['qty']
    gen1[L[0], GEN_STATUS] = 0
    gen1[L[1], [PMIN, QMIN, QMAX]] = array([-28, 0, 7])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0.copy()
    gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 25, 250],
        [2, 0, 0, 26, 1300],
        [2, 0, 0, 27, 2700]
    ]), zeros((3, 4))]
    gencost1[L[1], NCOST:NCOST + 8] = c_[array([
        [2, -28, -280, 0, 0]
    ]), zeros((1, 4))]
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers & P bids (1 gen with both)';
    gen2 = gen0.copy()
    gen2[1, PMIN] = -5
    bids['P']['qty'] = array([[0],  [3],  [20], [0], [28]], float)
    bids['P']['prc'] = array([[0], [50], [100], [0], [10]], float)
    gen, gencost = off2case(gen2, gencost0, offers, bids)

    gen1 = gen2.copy()
    gen1[G, PMAX] = offers['P']['qty']
    gen1[1, PMIN] = -sum( bids['P']['qty'][1, :] )
    gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([
        [-20, -10, 0],
        [-28,   0, 7]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :10].copy()
    gencost1[ix_(G, range(NCOST, NCOST + 7))] = array([
        [2,  0,    0, 25,  250,  0,    0],
        [3, -3, -150,  0,    0, 26, 1300],
        [2,  0,    0, 27, 2700,  0,    0]
    ])
    gencost1[ix_(L, range(NCOST, NCOST + 7))] = c_[array([
        [2, -20, -2000, 0, 0],
        [2, -28,  -280, 0, 0]
    ]), zeros((2, 2))]
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers & P bids, lim[\'P\'][\'max_offer\']/[\'min_bid\']'
    bids['P']['qty'] = array([[20],  [28]], float)
    bids['P']['prc'] = array([[100], [10]], float)
    lim['P']['min_bid'] = 50.0
    gen, gencost = off2case(gen0, gencost0, offers, bids, lim)

    gen1 = gen0.copy()
    gen1[G[:2], PMAX] = offers['P']['qty'][:2, :]
    gen1[r_[G[2], L[1]], GEN_STATUS] = 0
    gen1[L[0], [PMIN, QMIN, QMAX]] = array([-20, -10, 0])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0.copy()
    gencost1[ix_(G[:2], range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 25,  250],
        [2, 0, 0, 26, 1300]
    ]), zeros((2, 4))]
    gencost1[L[0], NCOST:NCOST + 9] = array([2, -20, -2000, 0, 0, 0, 0, 0, 0])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'P offers & P bids, lim[\'P\'][\'max_offer\']/[\'min_bid\'], multi-block'
    offers['P']['qty'] = array([[10,  40], [20, 30], [25, 25]], float)
    offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float)
    bids['P']['qty'] = array([[ 20, 10], [12, 18]], float)
    bids['P']['prc'] = array([[100, 60], [70, 10]], float)
    gen, gencost = off2case(gen0, gencost0, offers, bids, lim)

    gen1 = gen0.copy()
    gen1[G, PMAX] = array([10, 50, 25])
    gen1[ix_(L, [PMIN, QMIN, QMAX])] = array([
        [-30, -15, 0],
        [-12,   0, 3]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :10].copy()
    gencost1[ix_(G, range(NCOST, NCOST + 7))] = array([
        [2, 0, 0, 10,  100, 0,     0],
        [3, 0, 0, 20,  500, 50, 2450],
        [2, 0, 0, 25, 1250, 0,     0]
    ])
    gencost1[ix_(L, range(NCOST, NCOST + 7))] = array([
        [3, -30, -2600, -20, -2000, 0, 0],
        [2, -12,  -840,   0,     0, 0, 0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    ##-----  reactive  -----
    ## generator cost data
    #    1    startup    shutdown    n    x1    y1    ...    xn    yn
    #    2    startup    shutdown    n    c(n-1)    ...    c0
    gencost0 = array([
        [1,   0,  0, 4,   0,    0,  12,  240,  36, 1200, 60, 2400],
        [1, 100,  0, 4,   0,    0,  12,  240,  36, 1200, 60, 2400],
        [1,   0,  0, 4, -30,    0, -20, 1000, -10, 2000,  0, 3000],
        [1,   0,  0, 4,   0,    0,  12,  240,  36, 1200, 60, 2400],
        [1,   0, 50, 4, -30,    0, -20, 1000, -10, 2000,  0, 3000],
        [1,   0,  0, 4, -15, -150,   0,    0,  30,  150, 60,  450],
        [1, 100,  0, 2,   0,    0,   0,    0,   0,    0,  0,    0],
        [1,   0,  0, 3, -20,  -15, -10,  -10,   0,    0,  0,    0],
        [1,   0,  0, 3,   0,    0,  40,   80,  60,  180,  0,    0],
        [1,   0, 50, 2,   0,    0,   0,    0,   0,    0,  0,    0]
    ], float)

    t = 'PQ offers only';
    offers['P']['qty'] = array([[25], [26],  [27]], float)
    offers['P']['prc'] = array([[10], [50], [100]], float)
    offers['Q']['qty'] = array([[10], [20],  [30]], float)
    offers['Q']['prc'] = array([[10],  [5],   [1]], float)
    gen, gencost = off2case(gen0, gencost0, offers)

    gen1 = gen0.copy()
    gen1[G, PMAX] = offers['P']['qty']
    gen1[G, QMAX] = offers['Q']['qty']
    gen1[G, QMIN] = 0
    gen1[L, GEN_STATUS] = 0
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0.copy()
    gencost1[ix_(G, range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 25,  250],
        [2, 0, 0, 26, 1300],
        [2, 0, 0, 27, 2700]
    ]), zeros((3, 4))]
    gencost1[ix_(G + nGL - 1, range(NCOST, NCOST + 9))] = c_[array([
        [2, 0, 0, 10, 100],
        [2, 0, 0, 20, 100],
        [2, 0, 0, 30,  30]
    ]), zeros((3, 4))]

    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'PQ offers & PQ bids, lim.P/Q.max_offer/min_bid, multi-block';
    offers['P']['qty'] = array([[10,  40], [20, 30], [25, 25]], float)
    offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float)
    bids['P']['qty'] = array([[ 20, 10], [12, 18]], float)
    bids['P']['prc'] = array([[100, 60], [70, 10]], float)
    offers['Q']['qty'] = array([[ 5,  5], [10, 10], [15, 15]], float)
    offers['Q']['prc'] = array([[10, 20], [ 5, 60], [ 1, 10]], float)
    bids['Q']['qty'] = array([ 15, 10, 15,  15,  0], float)
    bids['Q']['prc'] = array([-10,  0,  5, -20, 10], float)
    lim['Q']['max_offer'] = 50.0
    lim['Q']['min_bid'] = -15.0
    gen, gencost = off2case(gen0, gencost0, offers, bids, lim)

    gen1 = gen0.copy()
    gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([
        [1,  10, 10, -15,  10],
        [1,  12, 50, -10,  10],
        [1, -10,  0,  -5,   0],
        [1,  12, 25,   0,  30],
        [0, -30,  0,   0, 7.5]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :12].copy()
    gencost1[:, NCOST - 1:NCOST + 9] = array([
        [2,   0,     0,  10,   100,   0,    0,  0,    0],
        [3,   0,     0,  20,   500,  50, 2450,  0,    0],
        [3, -30, -2600, -20, -2000,   0,    0,  0,    0],
        [2,   0,     0,  25,  1250,   0,    0,  0,    0],
        [4, -30,     0, -20,  1000, -10, 2000,  0, 3000],
        [4, -15,   150,   0,     0,   5,   50, 10,  150],
        [3, -10,     0,   0,     0,  10,   50,  0,    0],
        [2, -15,   -75,   0,     0,   0,    0,  0,    0],
        [3,   0,     0,  15,    15,  30,  165,  0,    0],
        [2,   0,     0,   0,     0,   0,    0,  0,    0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'PQ offers & PQ bids, for gen, no P, no shutdown';
    gen2 = gen0.copy()
    gen2[0, PMIN] = 0
    offers['P']['qty'] = array([[0, 40], [20, 30], [25, 25]], float)
    gen, gencost = off2case(gen2, gencost0, offers, bids, lim)

    gen1[0, [PMIN, PMAX, QMIN, QMAX]] = array([0, 0, -15, 10])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1[0, NCOST:NCOST + 9] = gencost0[0, NCOST:NCOST + 9]
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'PQ offers & PQ bids, for gen, no Q, no shutdown';
    offers['P']['qty'] = array([[10, 40], [20, 30], [25, 25]], float)
    offers['Q']['qty'] = array([[ 5,  5], [ 0, 10], [15, 15]], float)
    bids['Q']['qty'] = array([15, 0, 15, 15, 0], float)
    gen, gencost = off2case(gen0, gencost0, offers, bids, lim)

    gen1[0, [PMIN, PMAX, QMIN, QMAX]] = array([10, 10, -15, 10])    ## restore original
    gen1[1, [PMIN, PMAX, QMIN, QMAX]] = array([12, 50,   0,  0])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1[ix_([0, 1, 6], range(NCOST, NCOST + 9))] = array([
        [2, 0, 0, 10, 100,  0,    0, 0, 0],
        [3, 0, 0, 20, 500, 50, 2450, 0, 0],
        [2, 0, 0,  0,   0,  0,    0, 0, 0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'PQ offers & PQ bids, lim.P/Q.max_offer/min_bid, multi-block';
    offers['P']['qty'] = array([[10,  40], [20, 30], [25, 25]], float)
    offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float)
    bids['P']['qty'] = array([[10,   0], [12, 18]], float)
    bids['P']['prc'] = array([[100, 60], [70, 10]], float)
    offers['Q']['qty'] = array([[5, 5], [10, 10], [15, 15]], float)
    offers['Q']['prc'] = array([[10, 20], [5, 60], [1, 10]], float)
    bids['Q']['qty'] = array([15, 10, 10, 15, 0], float)
    bids['Q']['prc'] = array([-10, 0, 5, -20, 10], float)
    lim['Q']['max_offer'] = 50.0
    lim['Q']['min_bid'] = -15.0
    gen, gencost = off2case(gen0, gencost0, offers, bids, lim)

    gen1 = gen0.copy()
    gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([
        [1,  10, 10, -15, 10],
        [1,  12, 50, -10, 10],
        [1, -10,  0,  -5,  0],
        [1,  12, 25,   0, 30],
        [0, -30,  0,   0,  7.5]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :12].copy()
    gencost1[:, NCOST:NCOST + 9] = array([
        [2,   0,     0,  10,  100,   0,    0,  0,    0],
        [3,   0,     0,  20,  500,  50, 2450,  0,    0],
        [2, -10, -1000,   0,    0,   0,    0,  0,    0],
        [2,   0,     0,  25, 1250,   0,    0,  0,    0],
        [4, -30,     0, -20, 1000, -10, 2000,  0, 3000],
        [4, -15,   150,   0,    0,   5,   50, 10,  150],
        [3, -10,     0,   0,    0,  10,   50,  0,    0],
        [2, -10,   -50,   0,    0,   0,    0,  0,    0],
        [3,   0,     0,  15,   15,  30,  165,  0,    0],
        [2,   0,     0,   0,    0,   0,    0,  0,    0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'PQ offers & PQ bids, zero Q load w/P bid, shutdown bugfix';
    gen1 = gen0.copy()
    gen1[4, [QG, QMIN, QMAX]] = 0
    gen, gencost = off2case(gen1, gencost0, offers, bids, lim)

    gen1[:, [PMIN, PMAX, QMIN, QMAX]] = array([
        [ 10, 10, -15, 10],
        [ 12, 50, -10, 10],
        [-10,  0,  -5,  0],
        [ 12, 25,   0, 30],
        [-12,  0,   0,  0]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :12].copy()
    gencost1[:, NCOST - 1:NCOST + 9] = array([
        [2,   0,     0, 10,  100,  0,    0,  0,   0],
        [3,   0,     0, 20,  500, 50, 2450,  0,   0],
        [2, -10, -1000,  0,    0,  0,    0,  0,   0],
        [2,   0,     0, 25, 1250,  0,    0,  0,   0],
        [2, -12,  -840,  0,    0,  0,    0,  0,   0],
        [4, -15,   150,  0,    0,  5,   50, 10, 150],
        [3, -10,     0,  0,    0, 10,   50,  0,   0],
        [2, -10,   -50,  0,    0,  0,    0,  0,   0],
        [3,   0,     0, 15,   15, 30,  165,  0,   0],
        [2,   0,     0,  0,    0,  0,    0,  0,   0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t = 'PQ offers & PQ bids, non-zero Q load w/no P bid, shutdown bugfix';
    offers['P']['qty'] = array([[10,  40], [20, 30], [25, 25]], float)
    offers['P']['prc'] = array([[10, 100], [25, 65], [50, 90]], float)
    bids['P']['qty'] = array([[0, 10], [12, 18]], float)
    bids['P']['prc'] = array([[100, 40], [70, 10]], float)
    offers['Q']['qty'] = array([[ 5,  5], [10, 10], [15, 15]], float)
    offers['Q']['prc'] = array([[10, 20], [ 5, 60], [ 1, 10]], float)
    bids['Q']['qty'] = array([ 15, 10, 15,  15,  0], float)
    bids['Q']['prc'] = array([-10,  0,  5, -20, 10], float)
    lim['Q']['max_offer'] = 50.0
    lim['Q']['min_bid'] = -15.0
    gen, gencost = off2case(gen0, gencost0, offers, bids, lim)

    gen1 = gen0.copy()
    gen1[:, [GEN_STATUS, PMIN, PMAX, QMIN, QMAX]] = array([
        [1,  10, 10, -15, 10],
        [1,  12, 50, -10, 10],
        [0, -30,  0, -15,  0],
        [1,  12, 25,   0, 30],
        [0, -30,  0,   0, 7.5]
    ])
    t_is( gen, gen1, 8, [t, ' - gen'] )

    gencost1 = gencost0[:, :12].copy()
    gencost1[:, NCOST - 1:NCOST + 9] = array([
        [2,   0,   0,  10,  100,   0,    0,  0,    0],
        [3,   0,   0,  20,  500,  50, 2450,  0,    0],
        [4, -30,   0, -20, 1000, -10, 2000,  0, 3000],
        [2,   0,   0,  25, 1250,   0,    0,  0,    0],
        [4, -30,   0, -20, 1000, -10, 2000,  0, 3000],
        [4, -15, 150,   0,    0,   5,   50, 10,  150],
        [3, -10,   0,   0,    0,  10,   50,  0,    0],
        [3, -20, -15, -10,  -10,   0,    0,  0,    0],
        [3,   0,   0,  15,   15,  30,  165,  0,    0],
        [2,   0,   0,   0,    0,   0,    0,  0,    0]
    ])
    t_is( gencost, gencost1, 8, [t, ' - gencost'] )

    t_end()
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
def t_scale_load(quiet=False):
    """Tests for code in C{scale_load}.

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

    t_begin(n_tests, quiet)

    ppc = loadcase(join(dirname(__file__), 't_auction_case'))
    ppc['gen'][7, GEN_BUS] = 2    ## multiple d. loads per area, same bus as gen
    ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3])
    ## put it load before gen in matrix

    ppc['gen'] = vstack([ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]])
    ld = find(isload(ppc['gen']))
    a = [None] * 3
    lda = [None] * 3
    for k in range(3):
        a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1)  ## buses in area k
        tmp = find( in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k]) )
        lda[k] = ld[tmp]                       ## disp loads in area k

    area = [None] * 3
    for k in range(3):
        area[k] = {'fixed': {}, 'disp': {}, 'both': {}}
        area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD])
        area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD])
        area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN])
        area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN])
        area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX])
        area[k]['disp']['q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax']
        area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p']
        area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q']

    total = {'fixed': {}, 'disp': {}, 'both': {}}
    total['fixed']['p'] = sum(ppc['bus'][:, PD])
    total['fixed']['q'] = sum(ppc['bus'][:, QD])
    total['disp']['p'] = -sum(ppc['gen'][ld, PMIN])
    total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN])
    total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX])
    total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax']
    total['both']['p'] = total['fixed']['p'] + total['disp']['p']
    total['both']['q'] = total['fixed']['q'] + total['disp']['q']

    ##-----  single load zone, one scale factor  -----
    load = array([2])
    t = 'all fixed loads (PQ) * 2 : '
    bus, _ = scale_load(load, ppc['bus'])
    t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q'])
    opt = {'which': 'FIXED'}

    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)

    t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all fixed loads (P) * 2 : '
    opt = {'pq': 'P'}
    bus, _ = scale_load(load, ppc['bus'], None, None, opt)
    t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    opt = {'pq': 'P', 'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all loads (PQ) * 2 : '
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'])
    t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), load * total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), load * total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), load * total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all loads (P) * 2 : '
    opt = {'pq': 'P'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), load * total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all disp loads (PQ) * 2 : '
    opt = {'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), load * total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), load * total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all disp loads (P) * 2 : '
    opt = {'pq': 'P', 'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load * total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    ##-----  single load zone, one scale quantity  -----
    load = array([200.0])
    t = 'all fixed loads (PQ) => total = 200 : '
    opt = {'scale': 'QUANTITY'}
    bus, _ = scale_load(load, ppc['bus'], None, None, opt)
    t_is(sum(bus[:, PD]), load, 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), load / total['fixed']['p'] * total['fixed']['q'], 8, [t, 'total fixed Q'])
    opt = {'scale': 'QUANTITY', 'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), load - total['disp']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), (load - total['disp']['p'])/total['fixed']['p']*total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all fixed loads (P) => total = 200 : '
    opt = {'scale': 'QUANTITY', 'pq': 'P'}
    bus, _ = scale_load(load, ppc['bus'], None, None, opt)
    t_is(sum(bus[:, PD]), load, 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), load - total['disp']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all loads (PQ) => total = 200 : '
    opt = {'scale': 'QUANTITY'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), load / total['both']['p']*total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), load / total['both']['p']*total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load / total['both']['p']*total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), load / total['both']['p']*total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), load / total['both']['p']*total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all loads (P) => total = 200 : '
    opt = {'scale': 'QUANTITY', 'pq': 'P'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), load / total['both']['p']*total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load / total['both']['p']*total['disp']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all disp loads (PQ) => total = 200 : '
    opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load - total['fixed']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), (load - total['fixed']['p'])/total['disp']['p']*total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), (load - total['fixed']['p'])/total['disp']['p']*total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    t = 'all disp loads (P) => total = 200 : '
    opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    t_is(sum(bus[:, PD]), total['fixed']['p'], 8, [t, 'total fixed P'])
    t_is(sum(bus[:, QD]), total['fixed']['q'], 8, [t, 'total fixed Q'])
    t_is(-sum(gen[ld, PMIN]), load - total['fixed']['p'], 8, [t, 'total disp P'])
    t_is(-sum(gen[ld, QMIN]), total['disp']['qmin'], 8, [t, 'total disp Qmin'])
    t_is(-sum(gen[ld, QMAX]), total['disp']['qmax'], 8, [t, 'total disp Qmax'])

    ##-----  3 zones, area scale factors  -----
    t = 'area fixed loads (PQ) * [3 2 1] : '
    load = array([3, 2, 1])
    bus, _ = scale_load(load, ppc['bus'])
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))

    opt = {'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'area fixed loads (P) * [3 2 1] : '
    load = array([3, 2, 1])
    opt = {'pq': 'P'}
    bus, _ = scale_load(load, ppc['bus'], None, None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))

    opt = {'pq': 'P', 'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'all area loads (PQ) * [3 2 1] : '
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'])
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), load[k] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), load[k] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), load[k] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))


    t = 'all area loads (P) * [3 2 1] : '
    opt = {'pq': 'P'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'area disp loads (PQ) * [3 2 1] : '
    opt = {'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), load[k] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), load[k] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'area disp loads (P) * [3 2 1] : '
    opt = {'pq': 'P', 'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    ##-----  3 zones, area scale quantities  -----
    t = 'area fixed loads (PQ) => total = [100 80 60] : '
    load = array([100, 80, 60], float)
    opt = {'scale': 'QUANTITY'}
    bus, _ = scale_load(load, ppc['bus'], None, None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), load[k] / area[k]['fixed']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))

    opt = {'scale': 'QUANTITY', 'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] - area[k]['disp']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), (load[k] - area[k]['disp']['p']) / area[k]['fixed']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'area fixed loads (P) => total = [100 80 60] : '
    load = array([100, 80, 60], float)
    opt = {'scale': 'QUANTITY', 'pq': 'P'}
    bus, _ = scale_load(load, ppc['bus'], None, None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))

    opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'FIXED'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k]-area[k]['disp']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'all area loads (PQ) => total = [100 80 60] : '
    opt = {'scale': 'QUANTITY'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), load[k] / area[k]['both']['p'] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'all area loads (P) => total = [100 80 60] : '
    opt = {'scale': 'QUANTITY', 'pq': 'P'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), load[k] / area[k]['both']['p'] * area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k] / area[k]['both']['p'] * area[k]['disp']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'area disp loads (PQ) => total = [100 80 60] : throws expected exception'
    load = array([100, 80, 60], float)
    opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'}
    err = 0
    try:
        bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    except ScalingError as e:
        expected = 'scale_load: impossible to make zone 2 load equal 80 by scaling non-existent dispatchable load'
        err = expected not in str(e)
    t_ok(err, t)

    t = 'area disp loads (PQ) => total = [100 74.3941 60] : '
    load = array([100, area[1]['fixed']['p'], 60], float)
    opt = {'scale': 'QUANTITY', 'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k]-area[k]['fixed']['p'], 8, '%s area %d disp P' % (t, k))
        if k == 1:
            t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
            t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))
        else:
            t_is(-sum(gen[lda[k], QMIN]), (load[k] - area[k]['fixed']['p']) / area[k]['disp']['p'] * area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
            t_is(-sum(gen[lda[k], QMAX]), (load[k] - area[k]['fixed']['p']) / area[k]['disp']['p'] * area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    t = 'area disp loads (P) => total = [100 74.3941 60] : '
    opt = {'scale': 'QUANTITY', 'pq': 'P', 'which': 'DISPATCHABLE'}
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], None, opt)
    for k in range(len(load)):
        t_is(sum(bus[a[k], PD]), area[k]['fixed']['p'], 8, '%s area %d fixed P' % (t, k))
        t_is(sum(bus[a[k], QD]), area[k]['fixed']['q'], 8, '%s area %d fixed Q' % (t, k))
        t_is(-sum(gen[lda[k], PMIN]), load[k]-area[k]['fixed']['p'], 8, '%s area %d disp P' % (t, k))
        t_is(-sum(gen[lda[k], QMIN]), area[k]['disp']['qmin'], 8, '%s area %d disp Qmin' % (t, k))
        t_is(-sum(gen[lda[k], QMAX]), area[k]['disp']['qmax'], 8, '%s area %d disp Qmax' % (t, k))

    ##-----  explict single load zone  -----
    t = 'explicit single load zone'
    load_zone = zeros(ppc['bus'].shape[0])
    load_zone[[2, 3]] = 1
    load = array([2.0])
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], load_zone)
    Pd = ppc['bus'][:, PD]
    Pd[[2, 3]] = load * Pd[[2, 3]]
    t_is( bus[:, PD], Pd, 8, t)

    ##-----  explict multiple load zone  -----
    t = 'explicit multiple load zone'
    load_zone = zeros(ppc['bus'].shape[0])
    load_zone[[2, 3]] = 1
    load_zone[[6, 7]] = 2
    load = array([2, 0.5])
    bus, gen = scale_load(load, ppc['bus'], ppc['gen'], load_zone)
    Pd = ppc['bus'][:, PD]
    Pd[[2, 3]] = load[0] * Pd[[2, 3]]
    Pd[[6, 7]] = load[1] * Pd[[6, 7]]
    t_is( bus[:, PD], Pd, 8, t)

    t_end()
Ejemplo n.º 13
0
def runWorker(ID, s, output):

    client = EthJsonRpc('10.64.83.200', 39000 + ID)
    obj = web3.Web3(web3.HTTPProvider('http://10.64.83.200:3900' + str(ID)))
    print(client.eth_accounts()[0])
    #print(client1.eth_accounts()[1])

    print("Worker %d initialized successfully!" % (ID, ))

    all_gas = []
    nu = 0  #iteration count
    itermax = s.admmopt.iterMaxlocal  #get maximum iteration
    flag = False
    new_gas = 0

    start_balance = obj.eth.getBalance(
        obj.toChecksumAddress(client.eth_accounts()[0]))

    j = 0
    s.admmopt.tau = 1
    last_block = obj.eth.blockNumber
    while (1):
        trans_by_block = obj.eth.getBlockTransactionCount(last_block - j)
        if (trans_by_block > 0):
            #dest = list(s.nbor.keys())
            #if(ID==1):getNextValues(ID,s,client,obj,last_block - j, trans_by_block)

            #s.update_z()
            #s.choose_max_rho()
            break

        j = j + 1

    prev_convegenceTable = []
    P_history = []
    Q_history = []
    start_time2 = time()

    while nu <= itermax and not flag:
        if s.recvmsg:
            s.update_z()
            s.choose_max_rho()

            #print(ID,"i have rho", s.var["rho"])

        start_time = time()
        result = s.pipslopf_solver()

        end_time = time()

        if result['eflag'] and nu % 20 == 0:
            print('Subproblem %d at iteration %d solved!' % (ID, nu))
            # print("Time for solving subproblem %d: %ssecs to %ssecs" % (ID, start_time, end_time))

        s.update_x()
        P_history.append(sum(s.var['Pg']))
        Q_history.append(sum(s.var['Qg']))

        if s.recvmsg:  # not the initialization
            s.update_y()
            s.update_rho()

            prev_convegenceTable = s.gapAll[s.ID - 1]

        # check convergence
        #if(nu>10):flag =
        flag = s.converge()
        s.recvmsg = {}  # clear the received messages

        #s.send()

        dest = s.nbor.keys()

        for k in dest:
            # prepare the message to be sent to neighbor k
            #tm.sleep(0.05)
            msg3 = message()
            msg3.config(s.ID, k, s.var, s.nbor[k].tlidx['int'], s.gapAll)
            data2 = json.dumps(msg3.__dict__, cls=MyEncoder)

            json_data = json.JSONEncoder().encode(data2)

            json_data = '0x' + json_data.encode("utf-8").hex()

            sampleDict = obj.txpool.content.pending

            new_gas = new_gas + 18000000000 * obj.eth.estimateGas({
                'to':
                obj.toChecksumAddress(
                    '0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c'),
                'data':
                json_data
            })

            client.eth_sendTransaction(
                from_address=client.eth_accounts()[0],
                to_address="0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c",
                gas=0xf4240,
                gas_price=18000000000,
                value=1,  # 2441406250
                data=json_data)

        txpooljson = obj.txpool.content.pending.__dict__

        recvmsg = {}

        twait = s.admmopt.pollWaitingtime
        dest = list(s.nbor.keys())
        recvFlag = [0] * s.region['nnbor']
        arrived = 0  # number of arrived neighbors
        pollround = 0
        while arrived < s.region['nwait'] and pollround < 5:
            #for i in range(len(dest)):
            #k = dest[i]
            #s.recvmsg[k] = recvmsg[k]
            #recvFlag[i] = 1

            for k in txpooljson.keys():

                txpooljson2 = txpooljson[k].__dict__
                last_nonce = max(txpooljson2, key=int)
                #print(ID,", last nonce",last_nonce)
                last_nonce_dict = txpooljson2[last_nonce].__dict__

                hexjson = last_nonce_dict['input'][2:]
                jsonstring = codecs.decode(hexjson, "hex").decode('utf-8')

                jsonvalues = json.JSONDecoder().decode(jsonstring)
                values_dict = json.loads(jsonvalues, cls=MyDecoder)

                temp_msg = message()
                if (values_dict['fID'] in s.nbor.keys()):
                    for last_nonce in range(int(max(txpooljson2, key=int)), 0,
                                            -1):
                        last_nonce_dict = txpooljson2[str(last_nonce)].__dict__

                        hexjson = last_nonce_dict['input'][2:]
                        jsonstring = codecs.decode(hexjson,
                                                   "hex").decode('utf-8')

                        jsonvalues = json.JSONDecoder().decode(jsonstring)
                        values_dict = json.loads(jsonvalues, cls=MyDecoder)
                        if (values_dict['tID'] == s.ID): break

                #print(ID,"last nonce=",last_nonce,"from",values_dict['fID'])
                temp_msg.fID = values_dict['fID']
                temp_msg.tID = values_dict['tID']
                temp_msg.fields['AVmd'] = numpy.asarray(
                    values_dict['fields']['AVmd'])
                temp_msg.fields['AVms'] = numpy.asarray(
                    values_dict['fields']['AVms'])
                temp_msg.fields['AVad'] = numpy.asarray(
                    values_dict['fields']['AVad'])
                temp_msg.fields['AVas'] = numpy.asarray(
                    values_dict['fields']['AVas'])
                temp_msg.fields['ymd'] = numpy.asarray(
                    values_dict['fields']['ymd'])
                temp_msg.fields['yms'] = numpy.asarray(
                    values_dict['fields']['yms'])
                temp_msg.fields['yad'] = numpy.asarray(
                    values_dict['fields']['yad'])
                temp_msg.fields['yas'] = numpy.asarray(
                    values_dict['fields']['yas'])
                temp_msg.fields['rho'] = values_dict['fields']['rho']
                temp_msg.fields['convergeTable'] = values_dict['fields'][
                    'convergeTable']

                if (temp_msg.tID == s.ID):
                    recvmsg[temp_msg.fID] = temp_msg
                    #recvFlag[i] = 1

                arrived = len(recvmsg)
                pollround += 1

        s.recvmsg = copy.deepcopy(recvmsg)

        all_gas.append(new_gas)
        nu += 1

    # record results
    print("Worker %d finished!" % (ID, ))

    for k in dest:

        starting_point = message2()
        starting_point.config(s.ID, k, s.var, s.nbor[k].tlidx['int'], s.gapAll)
        data2 = json.dumps(starting_point.__dict__, cls=MyEncoder)
        json_data = json.JSONEncoder().encode(data2)
        json_data = '0x' + json_data.encode("utf-8").hex()
        sampleDict = obj.txpool.content.pending

        client.eth_sendTransaction(
            from_address=client.eth_accounts()[0],
            to_address="0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c",
            gas=0xf4240,
            gas_price=18000000000,
            value=1,  # 2441406250
            data=json_data)

    print(starting_point.__dict__)

    x, f, info, lmbda, output2 = result["x"], result["f"], result[
        "eflag"], result["lmbda"], result["output"]
    nx = len(x)
    nb = s.region['nb']
    ng = s.region['ng']
    iv = s.idx['var']
    bus = s.region['bus']
    gen = s.region['gen']
    branch = s.region['branch']
    baseMVA = s.region['baseMVA']
    Ybus = s.region['Ybus']
    ridx = s.idx['rbus']['int']
    # idx ranges
    iVa = iv['iVa']
    iVm = iv['iVm']
    iPg = iv['iPg']
    iQg = iv['iQg']
    # grab Pg and Qg
    gen[:, PG] = x[iPg] * s.region["baseMVA"]
    gen[:, QG] = x[iQg] * s.region["baseMVA"]
    bus[:, PD] = bus[:, PD] * s.region["baseMVA"]
    bus[:, QD] = bus[:, QD] * s.region["baseMVA"]
    # reconstruct V
    Va, Vm = x[iVa], x[iVm]
    V = Vm * exp(1j * Va)

    #print(V)
    nl = shape(branch)[0]  ## number of branches
    bus[:, VA] = Va * 180 / pi
    bus[:, VM] = Vm

    if shape(branch)[1] < MU_ANGMAX + 1:
        branch = c_[branch, zeros((nl, MU_ANGMAX + 1 - shape(branch)[1]))]

    Ybus2, Yf, Yt = makeYbus(baseMVA, bus, branch)
    #print(Yf)
    ## compute branch flows
    Sf = V[branch[:, F_BUS].astype(int)] * conj(
        Yf * V)  ## cplx pwr at "from" bus, p["u"].
    St = V[branch[:, T_BUS].astype(int)] * conj(
        Yt * V)  ## cplx pwr at "to" bus, p["u"].

    branch[:, PF] = Sf.real * baseMVA
    branch[:, QF] = Sf.imag * baseMVA
    branch[:, PT] = St.real * baseMVA
    branch[:, QT] = St.imag * baseMVA

    #gen[:, VG] = Vm[ gen[:, GEN_BUS].astype(int) ]

    nlam = len(lmbda["eqnonlin"]) // 2
    lamP = zeros(nb)  #for non-included pf balances use 0 as multiplier
    lamQ = zeros(nb)
    lamP[s.idx['rbus']['int']] = lmbda["eqnonlin"][:nlam] / s.region["baseMVA"]
    lamQ[s.idx['rbus']['int']] = lmbda["eqnonlin"][nlam:nlam +
                                                   nlam] / s.region["baseMVA"]

    ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen))
    objValue1 = 0
    objValue2 = 0

    fd = stdout
    fd.write('\n REGION %d' % (s.ID))

    fd.write(
        '\nBus/Area  Voltage          Generation             Load        ')
    fd.write('  Lambda($/MVA-hr)')
    fd.write(
        '\n  #   Mag(pu) Ang(deg)   P (MW)   Q (MVAr)   P (MW)   Q (MVAr)')
    fd.write('     P        Q   ')
    fd.write(
        '\n----- ------- --------  --------  --------  --------  --------')
    fd.write('  -------  -------')
    for i in range(nb):
        for glob, loc in s.idx["mapping"].items():
            if loc == i:
                busid = glob + 1
                #bus[i,BUS_I]=glob+1
                pass
        fd.write('\n%5d/' % busid)
        fd.write('%d%7.3f%9.3f' % tuple(bus[i, [BUS_AREA, VM, VA]]))
        if bus[i, BUS_TYPE] == REF:
            fd.write('*')
        else:
            fd.write(' ')
        g = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I])
                 & ~isload(gen))
        ld = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I])
                  & isload(gen))
        if any(g + 1):
            fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG])))
            objValue1 = objValue1 + (lamP[i]) * (sum(gen[g, PG]))
        else:
            fd.write('      -         -  ')
        if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1):
            if any(ld + 1):
                fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]),
                                            bus[i, QD] - sum(gen[ld, QG])))
                objValue2 = objValue2 + (lamP[i]) * (bus[i, PD] -
                                                     sum(gen[ld, PG]))
            else:
                fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]]))
        else:
            fd.write('       -         -   ')

        fd.write('%9.3f' % lamP[i])

        if abs(lamQ[i]) > 1e-4:
            fd.write('%8.3f' % lamQ[i])
        else:
            fd.write('     -')
    fd.write(
        '\n                        --------  --------  --------  --------')
    nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0))
    onld = find((gen[:, GEN_STATUS] > 0) & isload(gen))

    fd.write('\n               Total: %9.2f %9.2f %9.2f %9.2f' %
             (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) -
              sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG])))
    fd.write('\n')

    print("Local iteration of worker %d is %d" % (ID, nu))
    # calculate local generation cost
    gencost = s.region['gencost']
    pg = s.var['Pg']
    """
	objValue21=0
	for i in range(ng):
		if(pg[i]>0):
			objValue1 = objValue1 - gencost[i,COST+1]* pg[i]
			print(gencost[i,COST+1]* pg[i])
		else:
			objValue21 = objValue21 + gencost[i,COST+1]* (-pg[i])
			print(gencost[i,COST+1]* (-pg[i]))
	objValue2 = objValue21 - objValue2
	objValue = objValue1 + objValue2
	"""

    objValue = dot(gencost[:, COST], pg**2) + dot(
        gencost[:, COST + 1], pg) + sum(gencost[:, COST + 2])
    print(objValue)

    varDual = {
        'ymd': s.var['ymd'],
        'yad': s.var['yad'],
        'yms': s.var['yms'],
        'yas': s.var['yas']
    }
    varPrimal = {
        'Vm': s.var['Vm'],
        'Va': s.var['Va'],
        'Pg': s.var['Pg'],
        'Qg': s.var['Qg']
    }
    Result = {
        'objValue': objValue,
        'varPrimal': varPrimal,
        'varDual': varDual,
        'localiter': nu,
        'primalgap': s.pb['primalgap'],
        'dualgap': s.pb['dualgap']
    }

    ng = s.region['ng']
    for i in range(ng):
        for glob, loc in s.idx["mapping"].items():
            if gen[i, GEN_BUS] == loc:
                gen[i, GEN_BUS] = glob + 1
                break

    for i in range(nb):
        for glob, loc in s.idx["mapping"].items():
            if loc == i:

                bus[i, BUS_I] = glob + 1

    nl = s.region['nl']
    for i in range(nl):
        for glob, loc in s.idx["mapping"].items():
            #print(glob, loc, branch[i, F_BUS])
            if branch[i, F_BUS] == loc:
                #print(branch[tl1,F_BUS])
                branch[i, F_BUS] = glob + 1
                break
    for i in range(nl):
        for glob, loc in s.idx["mapping"].items():
            #print(glob, loc, branch[i, F_BUS])
            if branch[i, T_BUS] == loc:
                #print(branch[tl1,F_BUS])
                branch[i, T_BUS] = glob + 1
                break

    success = flag
    reg_nb = find(bus[:, BUS_AREA] == ID)

    lamP = lamP[ix_(reg_nb, )]

    lamP2 = numpy.array(lamP)

    reg_bus = bus[ix_(reg_nb, )]
    print(reg_bus[:, BUS_I])
    reg_lam = numpy.array((reg_bus[:, BUS_I], lamP))

    print(reg_lam)

    ppc = {}
    ppc["bus"], ppc["gen"], ppc["branch"] = reg_bus, gen, branch

    ids1 = reg_bus[:, BUS_I]
    ids = numpy.array(ids1)
    #ppc["success"] = success
    #ppc=ext2int(ppc)
    P_history = [i * s.region["baseMVA"] for i in P_history]
    Q_history = [i * s.region["baseMVA"] for i in Q_history]

    #results = int2ext(ppc)
    """
	fig = plt.figure()
	curfig = fig.add_subplot(1, 2, 1)
	curfig.plot(P_history, color = 'red', linewidth = 2.5, label = 'P')
	curfig = fig.add_subplot(1, 2, 2)
	curfig.plot(Q_history, color = 'blue', linewidth = 2.5, label = 'Q')
	curfig.set_yscale('log')
	curfig.legend(loc='upper right')
	"""

    #plt.show()
    """
	
	print(all_gas)
	
	while( obj.txpool.inspect.pending.__dict__): pass
	end_time2 = time()
	final_balance = obj.eth.getBalance(obj.toChecksumAddress(client.eth_accounts()[0]))
	print("sasasa",ID, "    ",start_balance - final_balance , "Time ", end_time2 - start_time2)
	"""

    output.put((ID - 1, Result, ppc["bus"], ppc["gen"], ppc["branch"], success,
                lamP2, ids, P_history, Q_history))
    """
Ejemplo n.º 14
0
def myprintpf(baseMVA,
              bus=None,
              gen=None,
              branch=None,
              f=None,
              success=None,
              et=None,
              fd=None,
              ppopt=None):
    """Prints power flow results.

    Prints power flow and optimal power flow results to C{fd} (a file
    descriptor which defaults to C{stdout}), with the details of what
    gets printed controlled by the optional C{ppopt} argument, which is a
    PYPOWER options vector (see L{ppoption} for details).

    The data can either be supplied in a single C{results} dict, or
    in the individual arguments: C{baseMVA}, C{bus}, C{gen}, C{branch}, C{f},
    C{success} and C{et}, where C{f} is the OPF objective function value,
    C{success} is C{True} if the solution converged and C{False} otherwise,
    and C{et} is the elapsed time for the computation in seconds. If C{f} is
    given, it is assumed that the output is from an OPF run, otherwise it is
    assumed to be a simple power flow run.

    Examples::
        ppopt = ppoptions(OUT_GEN=1, OUT_BUS=0, OUT_BRANCH=0)
        fd = open(fname, 'w+b')
        results = runopf(ppc)
        printpf(results)
        printpf(results, fd)
        printpf(results, fd, ppopt)
        printpf(baseMVA, bus, gen, branch, f, success, et)
        printpf(baseMVA, bus, gen, branch, f, success, et, fd)
        printpf(baseMVA, bus, gen, branch, f, success, et, fd, ppopt)
        fd.close()

    @author: Ray Zimmerman (PSERC Cornell)
    """
    ##----- initialization -----
    ## default arguments
    objValue = 0

    if isinstance(baseMVA, dict):
        have_results_struct = 1
        results = baseMVA
        if gen is None:
            ppopt = ppoption()  ## use default options
        else:
            ppopt = gen
        if (ppopt['OUT_ALL'] == 0):
            return  ## nothin' to see here, bail out now
        if bus is None:
            fd = stdout  ## print to stdout by default
        else:
            fd = bus
        baseMVA, bus, gen, branch, success, et = \
            results["baseMVA"], results["bus"], results["gen"], \
            results["branch"], results["success"], results["et"]
        if 'f' in results:
            f = results["f"]
        else:
            f = None
    else:
        have_results_struct = 0
        if ppopt is None:
            ppopt = ppoption()  ## use default options
            if fd is None:
                fd = stdout  ## print to stdout by default
        if ppopt['OUT_ALL'] == 0:
            return  ## nothin' to see here, bail out now

    isOPF = f is not None  ## FALSE -> only simple PF data, TRUE -> OPF data

    ## options
    isDC = ppopt['PF_DC']  ## use DC formulation?
    OUT_ALL = ppopt['OUT_ALL']
    OUT_ANY = OUT_ALL == 1  ## set to true if any pretty output is to be generated
    OUT_SYS_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_SYS_SUM'])
    OUT_AREA_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1)
                                      and ppopt['OUT_AREA_SUM'])
    OUT_BUS = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BUS'])
    OUT_BRANCH = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BRANCH'])
    OUT_GEN = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_GEN'])
    OUT_ANY = OUT_ANY | (
        (OUT_ALL == -1) and
        (OUT_SYS_SUM or OUT_AREA_SUM or OUT_BUS or OUT_BRANCH or OUT_GEN))

    if OUT_ALL == -1:
        OUT_ALL_LIM = ppopt['OUT_ALL_LIM']
    elif OUT_ALL == 1:
        OUT_ALL_LIM = 2
    else:
        OUT_ALL_LIM = 0

    OUT_ANY = OUT_ANY or (OUT_ALL_LIM >= 1)
    if OUT_ALL_LIM == -1:
        OUT_V_LIM = ppopt['OUT_V_LIM']
        OUT_LINE_LIM = ppopt['OUT_LINE_LIM']
        OUT_PG_LIM = ppopt['OUT_PG_LIM']
        OUT_QG_LIM = ppopt['OUT_QG_LIM']
    else:
        OUT_V_LIM = OUT_ALL_LIM
        OUT_LINE_LIM = OUT_ALL_LIM
        OUT_PG_LIM = OUT_ALL_LIM
        OUT_QG_LIM = OUT_ALL_LIM

    OUT_ANY = OUT_ANY or (
        (OUT_ALL_LIM == -1) and
        (OUT_V_LIM or OUT_LINE_LIM or OUT_PG_LIM or OUT_QG_LIM))
    ptol = 1e-4  ## tolerance for displaying shadow prices

    ## create map of external bus numbers to bus indices
    i2e = bus[:, BUS_I].astype(int)
    e2i = zeros(max(i2e) + 1, int)
    e2i[i2e] = arange(bus.shape[0])

    ## sizes of things
    nb = bus.shape[0]  ## number of buses
    nl = branch.shape[0]  ## number of branches
    ng = gen.shape[0]  ## number of generators

    ## zero out some data to make printout consistent for DC case
    if isDC:
        bus[:, r_[QD, BS]] = zeros((nb, 2))
        gen[:, r_[QG, QMAX, QMIN]] = zeros((ng, 3))
        branch[:, r_[BR_R, BR_B]] = zeros((nl, 2))

    ## parameters
    ties = find(
        bus[e2i[branch[:, F_BUS].astype(int)],
            BUS_AREA] != bus[e2i[branch[:, T_BUS].astype(int)], BUS_AREA])
    ## area inter-ties
    tap = ones(nl)  ## default tap ratio = 1 for lines
    xfmr = find(branch[:, TAP])  ## indices of transformers
    tap[xfmr] = branch[xfmr, TAP]  ## include transformer tap ratios
    tap = tap * exp(1j * pi / 180 * branch[:, SHIFT])  ## add phase shifters
    nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0))
    sorted_areas = sort(bus[:, BUS_AREA])
    ## area numbers
    s_areas = sorted_areas[r_[1, find(diff(sorted_areas)) + 1]]
    nzsh = find((bus[:, GS] != 0.0) | (bus[:, BS] != 0.0))
    allg = find(~isload(gen))
    ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen))
    onld = find((gen[:, GEN_STATUS] > 0) & isload(gen))
    V = bus[:, VM] * exp(-1j * pi / 180 * bus[:, VA])
    out = find(branch[:, BR_STATUS] == 0)  ## out-of-service branches
    nout = len(out)
    if isDC:
        loss = zeros(nl)
    else:
        loss = baseMVA * abs(V[e2i[ branch[:, F_BUS].astype(int) ]] / tap -
                             V[e2i[ branch[:, T_BUS].astype(int) ]])**2 / \
                    (branch[:, BR_R] - 1j * branch[:, BR_X])

    fchg = abs(V[e2i[branch[:, F_BUS].astype(int)]] /
               tap)**2 * branch[:, BR_B] * baseMVA / 2
    tchg = abs(
        V[e2i[branch[:, T_BUS].astype(int)]])**2 * branch[:,
                                                          BR_B] * baseMVA / 2
    loss[out] = zeros(nout)
    fchg[out] = zeros(nout)
    tchg[out] = zeros(nout)

    ##----- print the stuff -----
    if OUT_ANY:
        ## convergence & elapsed time
        if success:
            fd.write('\nConverged in %.2f seconds' % et)
        else:
            fd.write('\nDid not converge (%.2f seconds)\n' % et)

        ## objective function value
        if isOPF:
            fd.write('\nObjective Function Value = %.2f $/hr' % f)

    if OUT_SYS_SUM:
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     System Summary                                                           |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n\nHow many?                How much?              P (MW)            Q (MVAr)'
        )
        fd.write(
            '\n---------------------    -------------------  -------------  -----------------'
        )
        fd.write(
            '\nBuses         %6d     Total Gen Capacity   %7.1f       %7.1f to %.1f'
            % (nb, sum(gen[allg, PMAX]), sum(gen[allg,
                                                 QMIN]), sum(gen[allg, QMAX])))
        fd.write(
            '\nGenerators     %5d     On-line Capacity     %7.1f       %7.1f to %.1f'
            % (len(allg), sum(gen[ong, PMAX]), sum(
                gen[ong, QMIN]), sum(gen[ong, QMAX])))
        fd.write(
            '\nCommitted Gens %5d     Generation (actual)  %7.1f           %7.1f'
            % (len(ong), sum(gen[ong, PG]), sum(gen[ong, QG])))
        fd.write(
            '\nLoads          %5d     Load                 %7.1f           %7.1f'
            % (len(nzld) + len(onld), sum(bus[nzld, PD]) - sum(gen[onld, PG]),
               sum(bus[nzld, QD]) - sum(gen[onld, QG])))
        fd.write(
            '\n  Fixed        %5d       Fixed              %7.1f           %7.1f'
            % (len(nzld), sum(bus[nzld, PD]), sum(bus[nzld, QD])))
        fd.write(
            '\n  Dispatchable %5d       Dispatchable       %7.1f of %-7.1f%7.1f'
            % (len(onld), -sum(gen[onld, PG]), -sum(gen[onld, PMIN]),
               -sum(gen[onld, QG])))
        fd.write(
            '\nShunts         %5d     Shunt (inj)          %7.1f           %7.1f'
            % (len(nzsh), -sum(bus[nzsh, VM]**2 * bus[nzsh, GS]),
               sum(bus[nzsh, VM]**2 * bus[nzsh, BS])))
        fd.write(
            '\nBranches       %5d     Losses (I^2 * Z)     %8.2f          %8.2f'
            % (nl, sum(loss.real), sum(loss.imag)))
        fd.write(
            '\nTransformers   %5d     Branch Charging (inj)     -            %7.1f'
            % (len(xfmr), sum(fchg) + sum(tchg)))
        fd.write(
            '\nInter-ties     %5d     Total Inter-tie Flow %7.1f           %7.1f'
            % (len(ties), sum(abs(branch[ties, PF] - branch[ties, PT])) / 2,
               sum(abs(branch[ties, QF] - branch[ties, QT])) / 2))
        fd.write('\nAreas          %5d' % len(s_areas))
        fd.write('\n')
        fd.write(
            '\n                          Minimum                      Maximum')
        fd.write(
            '\n                 -------------------------  --------------------------------'
        )
        minv = min(bus[:, VM])
        mini = argmin(bus[:, VM])
        maxv = max(bus[:, VM])
        maxi = argmax(bus[:, VM])
        fd.write(
            '\nVoltage Magnitude %7.3f p.u. @ bus %-4d     %7.3f p.u. @ bus %-4d'
            % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
        minv = min(bus[:, VA])
        mini = argmin(bus[:, VA])
        maxv = max(bus[:, VA])
        maxi = argmax(bus[:, VA])
        fd.write(
            '\nVoltage Angle   %8.2f deg   @ bus %-4d   %8.2f deg   @ bus %-4d'
            % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
        if not isDC:
            maxv = max(loss.real)
            maxi = argmax(loss.real)
            fd.write(
                '\nP Losses (I^2*R)             -              %8.2f MW    @ line %d-%d'
                % (maxv, branch[maxi, F_BUS], branch[maxi, T_BUS]))
            maxv = max(loss.imag)
            maxi = argmax(loss.imag)
            fd.write(
                '\nQ Losses (I^2*X)             -              %8.2f MVAr  @ line %d-%d'
                % (maxv, branch[maxi, F_BUS], branch[maxi, T_BUS]))
        if isOPF:
            minv = min(bus[:, LAM_P])
            mini = argmin(bus[:, LAM_P])
            maxv = max(bus[:, LAM_P])
            maxi = argmax(bus[:, LAM_P])
            fd.write(
                '\nLambda P        %8.2f $/MWh @ bus %-4d   %8.2f $/MWh @ bus %-4d'
                % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
            minv = min(bus[:, LAM_Q])
            mini = argmin(bus[:, LAM_Q])
            maxv = max(bus[:, LAM_Q])
            maxi = argmax(bus[:, LAM_Q])
            fd.write(
                '\nLambda Q        %8.2f $/MWh @ bus %-4d   %8.2f $/MWh @ bus %-4d'
                % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
        fd.write('\n')

    ## bus data
    if OUT_BUS:
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     Bus Data                                                                 |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n Bus      Voltage          Generation             Load        ')
        if isOPF: fd.write('  Lambda($/MVA-hr)')
        fd.write(
            '\n  #   Mag(pu) Ang(deg)   P (MW)   Q (MVAr)   P (MW)   Q (MVAr)')
        if isOPF: fd.write('     P        Q   ')
        fd.write(
            '\n----- ------- --------  --------  --------  --------  --------')
        if isOPF: fd.write('  -------  -------')
        for i in range(nb):
            fd.write('\n%5d%7.3f%9.3f' % tuple(bus[i, [BUS_I, VM, VA]]))
            if bus[i, BUS_TYPE] == REF:
                fd.write('*')
            else:
                fd.write(' ')
            g = find((gen[:, GEN_STATUS] > 0)
                     & (gen[:, GEN_BUS] == bus[i, BUS_I]) & ~isload(gen))
            ld = find((gen[:, GEN_STATUS] > 0)
                      & (gen[:, GEN_BUS] == bus[i, BUS_I]) & isload(gen))
            if any(g + 1):
                fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG])))
                objValue = objValue + bus[i, LAM_P] * (sum(gen[g, PG]))
            else:
                fd.write('      -         -  ')

            if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1):
                if any(ld + 1):
                    fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]),
                                                bus[i, QD] - sum(gen[ld, QG])))
                    objValue = objValue + bus[i, LAM_P] * (bus[i, PD] -
                                                           sum(gen[ld, PG]))
                else:
                    fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]]))
            else:
                fd.write('       -         -   ')
            if isOPF:
                fd.write('%9.3f' % bus[i, LAM_P])
                if abs(bus[i, LAM_Q]) > ptol:
                    fd.write('%8.3f' % bus[i, LAM_Q])
                else:
                    fd.write('     -')
        fd.write(
            '\n                        --------  --------  --------  --------')
        fd.write('\n               Total: %9.2f %9.2f %9.2f %9.2f' %
                 (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) -
                  sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG])))
        fd.write('\n')
        fd.write('===========ObjValue = %f==============\n' % objValue)
Ejemplo n.º 15
0
def printpf(baseMVA,
            bus=None,
            gen=None,
            branch=None,
            f=None,
            success=None,
            et=None,
            fd=None,
            ppopt=None):
    """Prints power flow results.

    Prints power flow and optimal power flow results to C{fd} (a file
    descriptor which defaults to C{stdout}), with the details of what
    gets printed controlled by the optional C{ppopt} argument, which is a
    PYPOWER options vector (see L{ppoption} for details).

    The data can either be supplied in a single C{results} dict, or
    in the individual arguments: C{baseMVA}, C{bus}, C{gen}, C{branch}, C{f},
    C{success} and C{et}, where C{f} is the OPF objective function value,
    C{success} is C{True} if the solution converged and C{False} otherwise,
    and C{et} is the elapsed time for the computation in seconds. If C{f} is
    given, it is assumed that the output is from an OPF run, otherwise it is
    assumed to be a simple power flow run.

    Examples::
        ppopt = ppoptions(OUT_GEN=1, OUT_BUS=0, OUT_BRANCH=0)
        fd = open(fname, 'w+b')
        results = runopf(ppc)
        printpf(results)
        printpf(results, fd)
        printpf(results, fd, ppopt)
        printpf(baseMVA, bus, gen, branch, f, success, et)
        printpf(baseMVA, bus, gen, branch, f, success, et, fd)
        printpf(baseMVA, bus, gen, branch, f, success, et, fd, ppopt)
        fd.close()

    @author: Ray Zimmerman (PSERC Cornell)
    """
    ##----- initialization -----
    ## default arguments
    if isinstance(baseMVA, dict):
        have_results_struct = 1
        results = baseMVA
        if gen is None:
            ppopt = ppoption()  ## use default options
        else:
            ppopt = gen
        if (ppopt['OUT_ALL'] == 0):
            return  ## nothin' to see here, bail out now
        if bus is None:
            fd = stdout  ## print to stdout by default
        else:
            fd = bus
        baseMVA, bus, gen, branch, success, et = \
            results["baseMVA"], results["bus"], results["gen"], \
            results["branch"], results["success"], results["et"]
        if 'f' in results:
            f = results["f"]
        else:
            f = None
    else:
        have_results_struct = 0
        if ppopt is None:
            ppopt = ppoption()  ## use default options
            if fd is None:
                fd = stdout  ## print to stdout by default
        if ppopt['OUT_ALL'] == 0:
            return  ## nothin' to see here, bail out now

    isOPF = f is not None  ## FALSE -> only simple PF data, TRUE -> OPF data

    ## options
    isDC = ppopt['PF_DC']  ## use DC formulation?
    OUT_ALL = ppopt['OUT_ALL']
    OUT_ANY = OUT_ALL == 1  ## set to true if any pretty output is to be generated
    OUT_SYS_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_SYS_SUM'])
    OUT_AREA_SUM = (OUT_ALL == 1) or ((OUT_ALL == -1)
                                      and ppopt['OUT_AREA_SUM'])
    OUT_BUS = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BUS'])
    OUT_BRANCH = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_BRANCH'])
    OUT_GEN = (OUT_ALL == 1) or ((OUT_ALL == -1) and ppopt['OUT_GEN'])
    OUT_ANY = OUT_ANY | (
        (OUT_ALL == -1) and
        (OUT_SYS_SUM or OUT_AREA_SUM or OUT_BUS or OUT_BRANCH or OUT_GEN))

    if OUT_ALL == -1:
        OUT_ALL_LIM = ppopt['OUT_ALL_LIM']
    elif OUT_ALL == 1:
        OUT_ALL_LIM = 2
    else:
        OUT_ALL_LIM = 0

    OUT_ANY = OUT_ANY or (OUT_ALL_LIM >= 1)
    if OUT_ALL_LIM == -1:
        OUT_V_LIM = ppopt['OUT_V_LIM']
        OUT_LINE_LIM = ppopt['OUT_LINE_LIM']
        OUT_PG_LIM = ppopt['OUT_PG_LIM']
        OUT_QG_LIM = ppopt['OUT_QG_LIM']
    else:
        OUT_V_LIM = OUT_ALL_LIM
        OUT_LINE_LIM = OUT_ALL_LIM
        OUT_PG_LIM = OUT_ALL_LIM
        OUT_QG_LIM = OUT_ALL_LIM

    OUT_ANY = OUT_ANY or (
        (OUT_ALL_LIM == -1) and
        (OUT_V_LIM or OUT_LINE_LIM or OUT_PG_LIM or OUT_QG_LIM))
    ptol = 1e-4  ## tolerance for displaying shadow prices

    ## create map of external bus numbers to bus indices
    i2e = bus[:, BUS_I].astype(int)
    e2i = zeros(max(i2e) + 1, int)
    e2i[i2e] = arange(bus.shape[0])

    ## sizes of things
    nb = bus.shape[0]  ## number of buses
    nl = branch.shape[0]  ## number of branches
    ng = gen.shape[0]  ## number of generators

    ## zero out some data to make printout consistent for DC case
    if isDC:
        bus[:, r_[QD, BS]] = zeros((nb, 2))
        gen[:, r_[QG, QMAX, QMIN]] = zeros((ng, 3))
        branch[:, r_[BR_R, BR_B]] = zeros((nl, 2))

    ## parameters
    ties = find(
        bus[e2i[branch[:, F_BUS].real.astype(int)],
            BUS_AREA] != bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA])
    ## area inter-ties
    tap = ones(nl)  ## default tap ratio = 1 for lines
    xfmr = find(branch[:, TAP]).real  ## indices of transformers
    tap[xfmr] = branch[xfmr, TAP].real  ## include transformer tap ratios
    tap = tap * exp(-1j * pi / 180 * branch[:, SHIFT])  ## add phase shifters
    nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0))
    sorted_areas = sort(bus[:, BUS_AREA])
    ## area numbers
    s_areas = sorted_areas[r_[1, find(diff(sorted_areas)) + 1]]
    nzsh = find((bus[:, GS] != 0.0) | (bus[:, BS] != 0.0))
    allg = find(~isload(gen))
    ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen))
    onld = find((gen[:, GEN_STATUS] > 0) & isload(gen))
    V = bus[:, VM] * exp(-1j * pi / 180 * bus[:, VA])
    out = find(branch[:, BR_STATUS] == 0)  ## out-of-service branches
    nout = len(out)
    if isDC:
        loss = zeros(nl)
    else:
        loss = baseMVA * abs(V[e2i[ branch[:, F_BUS].real.astype(int) ]] / tap -
                             V[e2i[ branch[:, T_BUS].real.astype(int) ]])**2 / \
                    (branch[:, BR_R] - 1j * branch[:, BR_X])

    fchg = abs(V[e2i[branch[:, F_BUS].real.astype(int)]] /
               tap)**2 * branch[:, BR_B].real * baseMVA / 2
    tchg = abs(V[e2i[branch[:, T_BUS].real.astype(
        int)]])**2 * branch[:, BR_B].real * baseMVA / 2
    loss[out] = zeros(nout)
    fchg[out] = zeros(nout)
    tchg[out] = zeros(nout)

    ##----- print the stuff -----
    if OUT_ANY:
        ## convergence & elapsed time
        if success:
            fd.write('\nConverged in %.2f seconds' % et)
        else:
            fd.write('\nDid not converge (%.2f seconds)\n' % et)

        ## objective function value
        if isOPF:
            fd.write('\nObjective Function Value = %.2f $/hr' % f)

    if OUT_SYS_SUM:
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     System Summary                                                           |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n\nHow many?                How much?              P (MW)            Q (MVAr)'
        )
        fd.write(
            '\n---------------------    -------------------  -------------  -----------------'
        )
        fd.write(
            '\nBuses         %6d     Total Gen Capacity   %7.1f       %7.1f to %.1f'
            % (nb, sum(gen[allg, PMAX]), sum(gen[allg,
                                                 QMIN]), sum(gen[allg, QMAX])))
        fd.write(
            '\nGenerators     %5d     On-line Capacity     %7.1f       %7.1f to %.1f'
            % (len(allg), sum(gen[ong, PMAX]), sum(
                gen[ong, QMIN]), sum(gen[ong, QMAX])))
        fd.write(
            '\nCommitted Gens %5d     Generation (actual)  %7.1f           %7.1f'
            % (len(ong), sum(gen[ong, PG]), sum(gen[ong, QG])))
        fd.write(
            '\nLoads          %5d     Load                 %7.1f           %7.1f'
            % (len(nzld) + len(onld), sum(bus[nzld, PD]) - sum(gen[onld, PG]),
               sum(bus[nzld, QD]) - sum(gen[onld, QG])))
        fd.write(
            '\n  Fixed        %5d       Fixed              %7.1f           %7.1f'
            % (len(nzld), sum(bus[nzld, PD]), sum(bus[nzld, QD])))
        fd.write(
            '\n  Dispatchable %5d       Dispatchable       %7.1f of %-7.1f%7.1f'
            % (len(onld), -sum(gen[onld, PG]), -sum(gen[onld, PMIN]),
               -sum(gen[onld, QG])))
        fd.write(
            '\nShunts         %5d     Shunt (inj)          %7.1f           %7.1f'
            % (len(nzsh), -sum(bus[nzsh, VM]**2 * bus[nzsh, GS]),
               sum(bus[nzsh, VM]**2 * bus[nzsh, BS])))
        fd.write(
            '\nBranches       %5d     Losses (I^2 * Z)     %8.2f          %8.2f'
            % (nl, sum(loss.real), sum(loss.imag)))
        fd.write(
            '\nTransformers   %5d     Branch Charging (inj)     -            %7.1f'
            % (len(xfmr), sum(fchg) + sum(tchg)))
        fd.write(
            '\nInter-ties     %5d     Total Inter-tie Flow %7.1f           %7.1f'
            % (len(ties), sum(abs(branch[ties, PF] - branch[ties, PT])) / 2,
               sum(abs(branch[ties, QF] - branch[ties, QT])) / 2))
        fd.write('\nAreas          %5d' % len(s_areas))
        fd.write('\n')
        fd.write(
            '\n                          Minimum                      Maximum')
        fd.write(
            '\n                 -------------------------  --------------------------------'
        )
        minv = min(bus[:, VM])
        mini = argmin(bus[:, VM])
        maxv = max(bus[:, VM])
        maxi = argmax(bus[:, VM])
        fd.write(
            '\nVoltage Magnitude %7.3f p.u. @ bus %-4d     %7.3f p.u. @ bus %-4d'
            % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
        minv = min(bus[:, VA])
        mini = argmin(bus[:, VA])
        maxv = max(bus[:, VA])
        maxi = argmax(bus[:, VA])
        fd.write(
            '\nVoltage Angle   %8.2f deg   @ bus %-4d   %8.2f deg   @ bus %-4d'
            % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
        if not isDC:
            maxv = max(loss.real)
            maxi = argmax(loss.real)
            fd.write(
                '\nP Losses (I^2*R)             -              %8.2f MW    @ line %d-%d'
                % (maxv, branch[maxi, F_BUS].real, branch[maxi, T_BUS].real))
            maxv = max(loss.imag)
            maxi = argmax(loss.imag)
            fd.write(
                '\nQ Losses (I^2*X)             -              %8.2f MVAr  @ line %d-%d'
                % (maxv, branch[maxi, F_BUS].real, branch[maxi, T_BUS].real))
        if isOPF:
            minv = min(bus[:, LAM_P])
            mini = argmin(bus[:, LAM_P])
            maxv = max(bus[:, LAM_P])
            maxi = argmax(bus[:, LAM_P])
            fd.write(
                '\nLambda P        %8.2f $/MWh @ bus %-4d   %8.2f $/MWh @ bus %-4d'
                % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
            minv = min(bus[:, LAM_Q])
            mini = argmin(bus[:, LAM_Q])
            maxv = max(bus[:, LAM_Q])
            maxi = argmax(bus[:, LAM_Q])
            fd.write(
                '\nLambda Q        %8.2f $/MWh @ bus %-4d   %8.2f $/MWh @ bus %-4d'
                % (minv, bus[mini, BUS_I], maxv, bus[maxi, BUS_I]))
        fd.write('\n')

    if OUT_AREA_SUM:
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     Area Summary                                                             |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\nArea  # of      # of Gens        # of Loads         # of    # of   # of   # of'
        )
        fd.write(
            '\n Num  Buses   Total  Online   Total  Fixed  Disp    Shunt   Brchs  Xfmrs   Ties'
        )
        fd.write(
            '\n----  -----   -----  ------   -----  -----  -----   -----   -----  -----  -----'
        )
        for i in range(len(s_areas)):
            a = s_areas[i]
            ib = find(bus[:, BUS_AREA] == a)
            ig = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a)
                      & ~isload(gen))
            igon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a)
                        & (gen[:, GEN_STATUS] > 0) & ~isload(gen))
            ildon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a)
                         & (gen[:, GEN_STATUS] > 0) & isload(gen))
            inzld = find((bus[:, BUS_AREA] == a)
                         & logical_or(bus[:, PD], bus[:, QD]))
            inzsh = find((bus[:, BUS_AREA] == a)
                         & logical_or(bus[:, GS], bus[:, BS]))
            ibrch = find(
                (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a)
                & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a))
            in_tie = find(
                (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a)
                & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] != a))
            out_tie = find(
                (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] != a)
                & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a))
            if not any(xfmr + 1):
                nxfmr = 0
            else:
                nxfmr = len(
                    find((bus[e2i[branch[xfmr, F_BUS].real.astype(int)],
                              BUS_AREA] == a)
                         & (bus[e2i[branch[xfmr, T_BUS].real.astype(int)],
                                BUS_AREA] == a)))
            fd.write('\n%3d  %6d   %5d  %5d   %5d  %5d  %5d   %5d   %5d  %5d  %5d' %
                (a, len(ib), len(ig), len(igon), \
                len(inzld)+len(ildon), len(inzld), len(ildon), \
                len(inzsh), len(ibrch), nxfmr, len(in_tie)+len(out_tie)))

        fd.write(
            '\n----  -----   -----  ------   -----  -----  -----   -----   -----  -----  -----'
        )
        fd.write(
            '\nTot: %6d   %5d  %5d   %5d  %5d  %5d   %5d   %5d  %5d  %5d' %
            (nb, len(allg), len(ong), len(nzld) + len(onld), len(nzld),
             len(onld), len(nzsh), nl, len(xfmr), len(ties)))
        fd.write('\n')
        fd.write(
            '\nArea      Total Gen Capacity           On-line Gen Capacity         Generation'
        )
        fd.write(
            '\n Num     MW           MVAr            MW           MVAr             MW    MVAr'
        )
        fd.write(
            '\n----   ------  ------------------   ------  ------------------    ------  ------'
        )
        for i in range(len(s_areas)):
            a = s_areas[i]
            ig = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a)
                      & ~isload(gen))
            igon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a)
                        & (gen[:, GEN_STATUS] > 0) & ~isload(gen))
            fd.write(
                '\n%3d   %7.1f  %7.1f to %-.1f  %7.1f  %7.1f to %-7.1f   %7.1f %7.1f'
                %
                (a, sum(gen[ig, PMAX]), sum(gen[ig, QMIN]), sum(
                    gen[ig, QMAX]), sum(gen[igon, PMAX]), sum(gen[igon, QMIN]),
                 sum(gen[igon, QMAX]), sum(gen[igon, PG]), sum(gen[igon, QG])))

        fd.write(
            '\n----   ------  ------------------   ------  ------------------    ------  ------'
        )
        #        fd.write('\nTot:  %7.1f  %7.1f to %-7.1f  %7.1f  %7.1f to %-7.1f   %7.1f %7.1f' %
        #                (sum(gen[allg, PMAX]), sum(gen[allg, QMIN]), sum(gen[allg, QMAX]),
        #                sum(gen[ong, PMAX]), sum(gen[ong, QMIN]), sum(gen[ong, QMAX]),
        #                sum(gen[ong, PG]), sum(gen[ong, QG]) ))
        fd.write('\n')
        fd.write(
            '\nArea    Disp Load Cap       Disp Load         Fixed Load        Total Load'
        )
        fd.write(
            '\n Num      MW     MVAr       MW     MVAr       MW     MVAr       MW     MVAr'
        )
        fd.write(
            '\n----    ------  ------    ------  ------    ------  ------    ------  ------'
        )
        Qlim = (gen[:, QMIN] == 0) * gen[:, QMAX] + (gen[:, QMAX]
                                                     == 0) * gen[:, QMIN]
        for i in range(len(s_areas)):
            a = s_areas[i]
            ildon = find((bus[e2i[gen[:, GEN_BUS].astype(int)], BUS_AREA] == a)
                         & (gen[:, GEN_STATUS] > 0) & isload(gen))
            inzld = find((bus[:, BUS_AREA] == a)
                         & logical_or(bus[:, PD], bus[:, QD]))
            fd.write(
                '\n%3d    %7.1f %7.1f   %7.1f %7.1f   %7.1f %7.1f   %7.1f %7.1f'
                % (a, -sum(gen[ildon, PMIN]), -sum(Qlim[ildon]),
                   -sum(gen[ildon, PG]), -sum(gen[ildon, QG]),
                   sum(bus[inzld, PD]), sum(bus[inzld, QD]),
                   -sum(gen[ildon, PG]) + sum(bus[inzld, PD]),
                   -sum(gen[ildon, QG]) + sum(bus[inzld, QD])))

        fd.write(
            '\n----    ------  ------    ------  ------    ------  ------    ------  ------'
        )
        fd.write(
            '\nTot:   %7.1f %7.1f   %7.1f %7.1f   %7.1f %7.1f   %7.1f %7.1f' %
            (-sum(gen[onld, PMIN]), -sum(Qlim[onld]), -sum(gen[onld, PG]),
             -sum(gen[onld, QG]), sum(bus[nzld, PD]), sum(
                 bus[nzld, QD]), -sum(gen[onld, PG]) + sum(bus[nzld, PD]),
             -sum(gen[onld, QG]) + sum(bus[nzld, QD])))
        fd.write('\n')
        fd.write(
            '\nArea      Shunt Inj        Branch      Series Losses      Net Export'
        )
        fd.write(
            '\n Num      MW     MVAr     Charging      MW     MVAr       MW     MVAr'
        )
        fd.write(
            '\n----    ------  ------    --------    ------  ------    ------  ------'
        )
        for i in range(len(s_areas)):
            a = s_areas[i]
            inzsh = find((bus[:, BUS_AREA] == a)
                         & logical_or(bus[:, GS], bus[:, BS]))
            ibrch = find(
                (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a)
                & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a)
                & branch[:, BR_STATUS].astype(bool))
            in_tie = find(
                (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] != a)
                & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] == a)
                & branch[:, BR_STATUS].astype(bool))
            out_tie = find(
                (bus[e2i[branch[:, F_BUS].real.astype(int)], BUS_AREA] == a)
                & (bus[e2i[branch[:, T_BUS].real.astype(int)], BUS_AREA] != a)
                & branch[:, BR_STATUS].astype(bool))
            fd.write(
                '\n%3d    %7.1f %7.1f    %7.1f    %7.2f %7.2f   %7.1f %7.1f' %
                (a, -sum(bus[inzsh, VM]**2 * bus[inzsh, GS]),
                 sum(bus[inzsh, VM]**2 * bus[inzsh, BS]), sum(fchg[ibrch]) +
                 sum(tchg[ibrch]) + sum(fchg[out_tie]) + sum(tchg[in_tie]),
                 sum(real(loss[ibrch])) +
                 sum(real(loss[r_[in_tie, out_tie]])) / 2,
                 sum(imag(loss[ibrch])) +
                 sum(imag(loss[r_[in_tie, out_tie]])) / 2,
                 sum(branch[in_tie, PT]) + sum(branch[out_tie, PF]) -
                 sum(real(loss[r_[in_tie, out_tie]])) / 2,
                 sum(branch[in_tie, QT]) + sum(branch[out_tie, QF]) -
                 sum(imag(loss[r_[in_tie, out_tie]])) / 2))

        fd.write(
            '\n----    ------  ------    --------    ------  ------    ------  ------'
        )
        fd.write(
            '\nTot:   %7.1f %7.1f    %7.1f    %7.2f %7.2f       -       -' %
            (-sum(bus[nzsh, VM]**2 * bus[nzsh, GS]),
             sum(bus[nzsh, VM]**2 * bus[nzsh, BS]), sum(fchg) + sum(tchg),
             sum(real(loss)), sum(imag(loss))))
        fd.write('\n')

    ## generator data
    if OUT_GEN:
        if isOPF:
            genlamP = bus[e2i[gen[:, GEN_BUS].astype(int)], LAM_P]
            genlamQ = bus[e2i[gen[:, GEN_BUS].astype(int)], LAM_Q]

        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     Generator Data                                                           |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write('\n Gen   Bus   Status     Pg        Qg   ')
        if isOPF: fd.write('   Lambda ($/MVA-hr)')
        fd.write('\n  #     #              (MW)     (MVAr) ')
        if isOPF: fd.write('     P         Q    ')
        fd.write('\n----  -----  ------  --------  --------')
        if isOPF: fd.write('  --------  --------')
        for k in range(len(ong)):
            i = ong[k]
            fd.write('\n%3d %6d     %2d ' %
                     (i, gen[i, GEN_BUS], gen[i, GEN_STATUS]))
            if (gen[i, GEN_STATUS] > 0) & logical_or(gen[i, PG], gen[i, QG]):
                fd.write('%10.2f%10.2f' % (gen[i, PG], gen[i, QG]))
            else:
                fd.write('       -         -  ')
            if isOPF: fd.write('%10.2f%10.2f' % (genlamP[i], genlamQ[i]))

        fd.write('\n                     --------  --------')
        fd.write('\n            Total: %9.2f%10.2f' %
                 (sum(gen[ong, PG]), sum(gen[ong, QG])))
        fd.write('\n')
        if any(onld + 1):
            fd.write(
                '\n================================================================================'
            )
            fd.write(
                '\n|     Dispatchable Load Data                                                   |'
            )
            fd.write(
                '\n================================================================================'
            )
            fd.write('\n Gen   Bus   Status     Pd        Qd   ')
            if isOPF: fd.write('   Lambda ($/MVA-hr)')
            fd.write('\n  #     #              (MW)     (MVAr) ')
            if isOPF: fd.write('     P         Q    ')
            fd.write('\n----  -----  ------  --------  --------')
            if isOPF: fd.write('  --------  --------')
            for k in range(len(onld)):
                i = onld[k]
                fd.write('\n%3d %6d     %2d ' %
                         (i, gen[i, GEN_BUS], gen[i, GEN_STATUS]))
                if (gen[i, GEN_STATUS] > 0) & logical_or(
                        gen[i, PG], gen[i, QG]):
                    fd.write('%10.2f%10.2f' % (-gen[i, PG], -gen[i, QG]))
                else:
                    fd.write('       -         -  ')

                if isOPF: fd.write('%10.2f%10.2f' % (genlamP[i], genlamQ[i]))
            fd.write('\n                     --------  --------')
            fd.write('\n            Total: %9.2f%10.2f' %
                     (-sum(gen[onld, PG]), -sum(gen[onld, QG])))
            fd.write('\n')

    ## bus data
    if OUT_BUS:
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     Bus Data                                                                 |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n Bus      Voltage          Generation             Load        ')
        if isOPF: fd.write('  Lambda($/MVA-hr)')
        fd.write(
            '\n  #   Mag(pu) Ang(deg)   P (MW)   Q (MVAr)   P (MW)   Q (MVAr)')
        if isOPF: fd.write('     P        Q   ')
        fd.write(
            '\n----- ------- --------  --------  --------  --------  --------')
        if isOPF: fd.write('  -------  -------')
        for i in range(nb):
            fd.write('\n%5d%7.3f%9.3f' % tuple(bus[i, [BUS_I, VM, VA]]))
            if bus[i, BUS_TYPE] == REF:
                fd.write('*')
            else:
                fd.write(' ')
            g = find((gen[:, GEN_STATUS] > 0)
                     & (gen[:, GEN_BUS] == bus[i, BUS_I]) & ~isload(gen))
            ld = find((gen[:, GEN_STATUS] > 0)
                      & (gen[:, GEN_BUS] == bus[i, BUS_I]) & isload(gen))
            if any(g + 1):
                fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG])))
            else:
                fd.write('      -         -  ')

            if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1):
                if any(ld + 1):
                    fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]),
                                                bus[i, QD] - sum(gen[ld, QG])))
                else:
                    fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]]))
            else:
                fd.write('       -         -   ')
            if isOPF:
                fd.write('%9.3f' % bus[i, LAM_P])
                if abs(bus[i, LAM_Q]) > ptol:
                    fd.write('%8.3f' % bus[i, LAM_Q])
                else:
                    fd.write('     -')
        fd.write(
            '\n                        --------  --------  --------  --------')
        fd.write('\n               Total: %9.2f %9.2f %9.2f %9.2f' %
                 (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) -
                  sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG])))
        fd.write('\n')

    ## branch data
    if OUT_BRANCH:
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\n|     Branch Data                                                              |'
        )
        fd.write(
            '\n================================================================================'
        )
        fd.write(
            '\nBrnch   From   To    From Bus Injection   To Bus Injection     Loss (I^2 * Z)  '
        )
        fd.write(
            '\n  #     Bus    Bus    P (MW)   Q (MVAr)   P (MW)   Q (MVAr)   P (MW)   Q (MVAr)'
        )
        fd.write(
            '\n-----  -----  -----  --------  --------  --------  --------  --------  --------'
        )
        for i in range(nl):
            fd.write(
                '\n%4d%7d%7d%10.2f%10.2f%10.2f%10.2f%10.3f%10.2f' %
                (i, branch[i, F_BUS].real, branch[i, T_BUS].real,
                 branch[i, PF].real, branch[i, QF].real, branch[i, PT].real,
                 branch[i, QT].real, loss[i].real, loss[i].imag))
        fd.write(
            '\n                                                             --------  --------'
        )
        fd.write(
            '\n                                                    Total:%10.3f%10.2f'
            % (sum(real(loss)), sum(imag(loss))))
        fd.write('\n')

    ##-----  constraint data  -----
    if isOPF:
        ctol = ppopt['OPF_VIOLATION']  ## constraint violation tolerance
        ## voltage constraints
        if (not isDC) & (
                OUT_V_LIM == 2 |
            (OUT_V_LIM == 1 &
             (any(bus[:, VM] < bus[:, VMIN] + ctol)
              | any(bus[:, VM] > bus[:, VMAX] - ctol)
              | any(bus[:, MU_VMIN] > ptol) | any(bus[:, MU_VMAX] > ptol)))):
            fd.write(
                '\n================================================================================'
            )
            fd.write(
                '\n|     Voltage Constraints                                                      |'
            )
            fd.write(
                '\n================================================================================'
            )
            fd.write('\nBus #  Vmin mu    Vmin    |V|   Vmax    Vmax mu')
            fd.write('\n-----  --------   -----  -----  -----   --------')
            for i in range(nb):
                if (OUT_V_LIM == 2) | (OUT_V_LIM == 1 &
                                       ((bus[i, VM] < bus[i, VMIN] + ctol) |
                                        (bus[i, VM] > bus[i, VMAX] - ctol) |
                                        (bus[i, MU_VMIN] > ptol) |
                                        (bus[i, MU_VMAX] > ptol))):
                    fd.write('\n%5d' % bus[i, BUS_I])
                    if ((bus[i, VM] < bus[i, VMIN] + ctol) |
                        (bus[i, MU_VMIN] > ptol)):
                        fd.write('%10.3f' % bus[i, MU_VMIN])
                    else:
                        fd.write('      -   ')

                    fd.write('%8.3f%7.3f%7.3f' %
                             tuple(bus[i, [VMIN, VM, VMAX]]))
                    if (bus[i, VM] > bus[i, VMAX] - ctol) | (bus[i, MU_VMAX] >
                                                             ptol):
                        fd.write('%10.3f' % bus[i, MU_VMAX])
                    else:
                        fd.write('      -    ')
            fd.write('\n')

        ## generator P constraints
        if (OUT_PG_LIM == 2) | \
                ((OUT_PG_LIM == 1) & (any(gen[ong, PG] < gen[ong, PMIN] + ctol) |
                                      any(gen[ong, PG] > gen[ong, PMAX] - ctol) |
                                      any(gen[ong, MU_PMIN] > ptol) |
                                      any(gen[ong, MU_PMAX] > ptol))) | \
                ((not isDC) & ((OUT_QG_LIM == 2) |
                ((OUT_QG_LIM == 1) & (any(gen[ong, QG] < gen[ong, QMIN] + ctol) |
                                      any(gen[ong, QG] > gen[ong, QMAX] - ctol) |
                                      any(gen[ong, MU_QMIN] > ptol) |
                                      any(gen[ong, MU_QMAX] > ptol))))):
            fd.write(
                '\n================================================================================'
            )
            fd.write(
                '\n|     Generation Constraints                                                   |'
            )
            fd.write(
                '\n================================================================================'
            )

        if (OUT_PG_LIM == 2) | (
            (OUT_PG_LIM == 1) &
            (any(gen[ong, PG] < gen[ong, PMIN] + ctol)
             | any(gen[ong, PG] > gen[ong, PMAX] - ctol)
             | any(gen[ong, MU_PMIN] > ptol) | any(gen[ong, MU_PMAX] > ptol))):
            fd.write('\n Gen   Bus                Active Power Limits')
            fd.write(
                '\n  #     #    Pmin mu    Pmin       Pg       Pmax    Pmax mu'
            )
            fd.write(
                '\n----  -----  -------  --------  --------  --------  -------'
            )
            for k in range(len(ong)):
                i = ong[k]
                if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) &
                                        ((gen[i, PG] < gen[i, PMIN] + ctol) |
                                         (gen[i, PG] > gen[i, PMAX] - ctol) |
                                         (gen[i, MU_PMIN] > ptol) |
                                         (gen[i, MU_PMAX] > ptol))):
                    fd.write('\n%4d%6d ' % (i, gen[i, GEN_BUS]))
                    if (gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, MU_PMIN] >
                                                             ptol):
                        fd.write('%8.3f' % gen[i, MU_PMIN])
                    else:
                        fd.write('     -  ')
                    if gen[i, PG]:
                        fd.write('%10.2f%10.2f%10.2f' %
                                 tuple(gen[i, [PMIN, PG, PMAX]]))
                    else:
                        fd.write('%10.2f       -  %10.2f' %
                                 tuple(gen[i, [PMIN, PMAX]]))
                    if (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMAX] >
                                                             ptol):
                        fd.write('%9.3f' % gen[i, MU_PMAX])
                    else:
                        fd.write('      -  ')
            fd.write('\n')

        ## generator Q constraints
        if (not isDC) & ((OUT_QG_LIM == 2) | (
            (OUT_QG_LIM == 1) &
            (any(gen[ong, QG] < gen[ong, QMIN] + ctol)
             | any(gen[ong, QG] > gen[ong, QMAX] - ctol) |
             any(gen[ong, MU_QMIN] > ptol) | any(gen[ong, MU_QMAX] > ptol)))):
            fd.write('\nGen  Bus              Reactive Power Limits')
            fd.write(
                '\n #    #   Qmin mu    Qmin       Qg       Qmax    Qmax mu')
            fd.write(
                '\n---  ---  -------  --------  --------  --------  -------')
            for k in range(len(ong)):
                i = ong[k]
                if (OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) &
                                        ((gen[i, QG] < gen[i, QMIN] + ctol) |
                                         (gen[i, QG] > gen[i, QMAX] - ctol) |
                                         (gen[i, MU_QMIN] > ptol) |
                                         (gen[i, MU_QMAX] > ptol))):
                    fd.write('\n%3d%5d' % (i, gen[i, GEN_BUS]))
                    if (gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, MU_QMIN] >
                                                             ptol):
                        fd.write('%8.3f' % gen[i, MU_QMIN])
                    else:
                        fd.write('     -  ')
                    if gen[i, QG]:
                        fd.write('%10.2f%10.2f%10.2f' %
                                 tuple(gen[i, [QMIN, QG, QMAX]]))
                    else:
                        fd.write('%10.2f       -  %10.2f' %
                                 tuple(gen[i, [QMIN, QMAX]]))

                    if (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMAX] >
                                                             ptol):
                        fd.write('%9.3f' % gen[i, MU_QMAX])
                    else:
                        fd.write('      -  ')
            fd.write('\n')

        ## dispatchable load P constraints
        if (OUT_PG_LIM == 2) | (OUT_QG_LIM == 2) | \
                ((OUT_PG_LIM == 1) & (any(gen[onld, PG] < gen[onld, PMIN] + ctol) |
                                      any(gen[onld, PG] > gen[onld, PMAX] - ctol) |
                                      any(gen[onld, MU_PMIN] > ptol) |
                                      any(gen[onld, MU_PMAX] > ptol))) | \
                ((OUT_QG_LIM == 1) & (any(gen[onld, QG] < gen[onld, QMIN] + ctol) |
                                      any(gen[onld, QG] > gen[onld, QMAX] - ctol) |
                                      any(gen[onld, MU_QMIN] > ptol) |
                                      any(gen[onld, MU_QMAX] > ptol))):
            fd.write(
                '\n================================================================================'
            )
            fd.write(
                '\n|     Dispatchable Load Constraints                                            |'
            )
            fd.write(
                '\n================================================================================'
            )
        if (OUT_PG_LIM == 2) | (
            (OUT_PG_LIM == 1) &
            (any(gen[onld, PG] < gen[onld, PMIN] + ctol)
             | any(gen[onld, PG] > gen[onld, PMAX] - ctol) |
             any(gen[onld, MU_PMIN] > ptol) | any(gen[onld, MU_PMAX] > ptol))):
            fd.write('\nGen  Bus               Active Power Limits')
            fd.write(
                '\n #    #   Pmin mu    Pmin       Pg       Pmax    Pmax mu')
            fd.write(
                '\n---  ---  -------  --------  --------  --------  -------')
            for k in range(len(onld)):
                i = onld[k]
                if (OUT_PG_LIM == 2) | ((OUT_PG_LIM == 1) &
                                        ((gen[i, PG] < gen[i, PMIN] + ctol) |
                                         (gen[i, PG] > gen[i, PMAX] - ctol) |
                                         (gen[i, MU_PMIN] > ptol) |
                                         (gen[i, MU_PMAX] > ptol))):
                    fd.write('\n%3d%5d' % (i, gen[i, GEN_BUS]))
                    if (gen[i, PG] < gen[i, PMIN] + ctol) | (gen[i, MU_PMIN] >
                                                             ptol):
                        fd.write('%8.3f' % gen[i, MU_PMIN])
                    else:
                        fd.write('     -  ')
                    if gen[i, PG]:
                        fd.write('%10.2f%10.2f%10.2f' %
                                 gen[i, [PMIN, PG, PMAX]])
                    else:
                        fd.write('%10.2f       -  %10.2f' %
                                 gen[i, [PMIN, PMAX]])

                    if (gen[i, PG] > gen[i, PMAX] - ctol) | (gen[i, MU_PMAX] >
                                                             ptol):
                        fd.write('%9.3f' % gen[i, MU_PMAX])
                    else:
                        fd.write('      -  ')
            fd.write('\n')

        ## dispatchable load Q constraints
        if (not isDC) & ((OUT_QG_LIM == 2) |
                         ((OUT_QG_LIM == 1) &
                          (any(gen[onld, QG] < gen[onld, QMIN] + ctol)
                           | any(gen[onld, QG] > gen[onld, QMAX] - ctol)
                           | any(gen[onld, MU_QMIN] > ptol)
                           | any(gen[onld, MU_QMAX] > ptol)))):
            fd.write('\nGen  Bus              Reactive Power Limits')
            fd.write(
                '\n #    #   Qmin mu    Qmin       Qg       Qmax    Qmax mu')
            fd.write(
                '\n---  ---  -------  --------  --------  --------  -------')
            for k in range(len(onld)):
                i = onld[k]
                if (OUT_QG_LIM == 2) | ((OUT_QG_LIM == 1) &
                                        ((gen[i, QG] < gen[i, QMIN] + ctol) |
                                         (gen[i, QG] > gen[i, QMAX] - ctol) |
                                         (gen[i, MU_QMIN] > ptol) |
                                         (gen[i, MU_QMAX] > ptol))):
                    fd.write('\n%3d%5d' % (i, gen(i, GEN_BUS)))
                    if (gen[i, QG] < gen[i, QMIN] + ctol) | (gen[i, MU_QMIN] >
                                                             ptol):
                        fd.write('%8.3f' % gen[i, MU_QMIN])
                    else:
                        fd.write('     -  ')

                    if gen[i, QG]:
                        fd.write('%10.2f%10.2f%10.2f' %
                                 gen[i, [QMIN, QG, QMAX]])
                    else:
                        fd.write('%10.2f       -  %10.2f' %
                                 gen[i, [QMIN, QMAX]])

                    if (gen[i, QG] > gen[i, QMAX] - ctol) | (gen[i, MU_QMAX] >
                                                             ptol):
                        fd.write('%9.3f' % gen[i, MU_QMAX])
                    else:
                        fd.write('      -  ')
            fd.write('\n')

        ## line flow constraints
        if (ppopt['OPF_FLOW_LIM'] == 1) | isDC:  ## P limit
            Ff = branch[:, PF]
            Ft = branch[:, PT]
            strg = '\n  #     Bus    Pf  mu     Pf      |Pmax|      Pt      Pt  mu   Bus'
        elif ppopt['OPF_FLOW_LIM'] == 2:  ## |I| limit
            Ff = abs((branch[:, PF] + 1j * branch[:, QF]) /
                     V[e2i[branch[:, F_BUS].astype(int)]])
            Ft = abs((branch[:, PT] + 1j * branch[:, QT]) /
                     V[e2i[branch[:, T_BUS].astype(int)]])
            strg = '\n  #     Bus   |If| mu    |If|     |Imax|     |It|    |It| mu   Bus'
        else:  ## |S| limit
            Ff = abs(branch[:, PF] + 1j * branch[:, QF])
            Ft = abs(branch[:, PT] + 1j * branch[:, QT])
            strg = '\n  #     Bus   |Sf| mu    |Sf|     |Smax|     |St|    |St| mu   Bus'

        if (OUT_LINE_LIM == 2) | (
            (OUT_LINE_LIM == 1) &
            (any((branch[:, RATE_A] != 0) &
                 (abs(Ff) > branch[:, RATE_A] - ctol)) | any(
                     (branch[:, RATE_A] != 0) &
                     (abs(Ft) > branch[:, RATE_A] - ctol))
             | any(branch[:, MU_SF] > ptol) | any(branch[:, MU_ST] > ptol))):
            fd.write(
                '\n================================================================================'
            )
            fd.write(
                '\n|     Branch Flow Constraints                                                  |'
            )
            fd.write(
                '\n================================================================================'
            )
            fd.write(
                '\nBrnch   From     "From" End        Limit       "To" End        To'
            )
            fd.write(strg)
            fd.write(
                '\n-----  -----  -------  --------  --------  --------  -------  -----'
            )
            for i in range(nl):
                if (OUT_LINE_LIM == 2) | ((OUT_LINE_LIM == 1) & (
                    ((branch[i, RATE_A] != 0) &
                     (abs(Ff[i]) > branch[i, RATE_A] - ctol)) |
                    ((branch[i, RATE_A] != 0) &
                     (abs(Ft[i]) > branch[i, RATE_A] - ctol)) |
                    (branch[i, MU_SF] > ptol) | (branch[i, MU_ST] > ptol))):
                    fd.write('\n%4d%7d' % (i, branch[i, F_BUS]))
                    if (Ff[i] > branch[i, RATE_A] - ctol) | (branch[i, MU_SF] >
                                                             ptol):
                        fd.write('%10.3f' % branch[i, MU_SF])
                    else:
                        fd.write('      -   ')

                    fd.write('%9.2f%10.2f%10.2f' %
                             (Ff[i], branch[i, RATE_A], Ft[i]))
                    if (Ft[i] > branch[i, RATE_A] - ctol) | (branch[i, MU_ST] >
                                                             ptol):
                        fd.write('%10.3f' % branch[i, MU_ST])
                    else:
                        fd.write('      -   ')
                    fd.write('%6d' % branch[i, T_BUS])
            fd.write('\n')

    ## execute userfcn callbacks for 'printpf' stage
    if have_results_struct and 'userfcn' in results:
        if not isOPF:  ## turn off option for all constraints if it isn't an OPF
            ppopt = ppoption(ppopt, 'OUT_ALL_LIM', 0)
        run_userfcn(results["userfcn"], 'printpf', results, fd, ppopt)
Ejemplo n.º 16
0
def userfcn_dcline_ext2int(ppc, args):
    """This is the 'ext2int' stage userfcn callback that prepares the input
    data for the formulation stage. It expects to find a 'dcline' field
    in ppc as described above. The optional args are not currently used.
    It adds two dummy generators for each in-service DC line, with the
    appropriate upper and lower generation bounds and corresponding
    zero-cost entries in gencost.
    """
    c = idx_dcline.c

    ## initialize some things
    if 'dclinecost' in ppc:
        havecost = True
    else:
        havecost = False

    ## save version with external indexing
    ppc['order']['ext']['dcline'] = ppc['dcline']              ## external indexing
    if havecost:
        ppc['order']['ext']['dclinecost'] = ppc['dclinecost']  ## external indexing

    ## work with only in-service DC lines
    ppc['order']['dcline']['status']['on']  = find(ppc['dcline'][:, c.BR_STATUS] >  0)
    ppc['order']['dcline']['status']['off'] = find(ppc['dcline'][:, c.BR_STATUS] <= 0)

    ## remove out-of-service DC lines
    dc = ppc['dcline'][ppc['order']['dcline']['status']['on'], :] ## only in-service DC lines
    if havecost:
        dcc = ppc['dclinecost'][ppc['order']['dcline']['status']['on'], :]    ## only in-service DC lines
        ppc['dclinecost'] = dcc

    ndc = dc.shape[0]          ## number of in-service DC lines
    o = ppc['order']

    ##-----  convert stuff to internal indexing  -----
    dc[:, c.F_BUS] = o['bus']['e2i'][dc[:, c.F_BUS]]
    dc[:, c.T_BUS] = o['bus']['e2i'][dc[:, c.T_BUS]]
    ppc['dcline'] = dc

    ##-----  create gens to represent DC line terminals  -----
    ## ensure consistency of initial values of PF, PT and losses
    ## (for simple power flow cases)
    dc[:, c.PT] = dc[:, c.PF] - (dc[:, c.LOSS0] + dc[:, c.LOSS1] * dc[:, c.PF])

    ## create gens
    fg = zeros(ndc, ppc['gen'].shape[1])
    fg[:, MBASE]        = 100
    fg[:, GEN_STATUS]   =  dc[:, c.BR_STATUS]   ## status (should be all 1's)
    fg[:, PMIN]         = -Inf
    fg[:, PMAX]         =  Inf
    tg = fg
    fg[:, GEN_BUS]      =  dc[:, c.F_BUS]       ## from bus
    tg[:, GEN_BUS]      =  dc[:, c.T_BUS]       ## to bus
    fg[:, PG]           = -dc[:, c.PF]          ## flow (extracted at "from")
    tg[:, PG]           =  dc[:, c.PT]          ## flow (injected at "to")
    fg[:, QG]           =  dc[:, c.QF]          ## VAr injection at "from"
    tg[:, QG]           =  dc[:, c.QT]          ## VAr injection at "to"
    fg[:, VG]           =  dc[:, c.VF]          ## voltage set-point at "from"
    tg[:, VG]           =  dc[:, c.VT]          ## voltage set-point at "to"
    k = find(dc[:, c.PMIN] >= 0)           ## min positive direction flow
    if len(k) > 0:                             ## contrain at "from" end
        fg[k, PMAX]     = -dc[k, c.PMIN]       ## "from" extraction lower lim

    k = find(dc[:, c.PMAX] >= 0)           ## max positive direction flow
    if len(k) > 0:                             ## contrain at "from" end
        fg[k, PMIN]     = -dc[k, c.PMAX]       ## "from" extraction upper lim

    k = find(dc[:, c.PMIN] < 0)            ## max negative direction flow
    if len(k) > 0:                             ## contrain at "to" end
        tg[k, PMIN]     =  dc[k, c.PMIN]       ## "to" injection lower lim

    k = find(dc[:, c.PMAX] < 0)            ## min negative direction flow
    if len(k) > 0:                             ## contrain at "to" end
        tg[k, PMAX]     =  dc[k, c.PMAX]       ## "to" injection upper lim

    fg[:, QMIN]         =  dc[:, c.QMINF]      ## "from" VAr injection lower lim
    fg[:, QMAX]         =  dc[:, c.QMAXF]      ## "from" VAr injection upper lim
    tg[:, QMIN]         =  dc[:, c.QMINT]      ##  "to"  VAr injection lower lim
    tg[:, QMAX]         =  dc[:, c.QMAXT]      ##  "to"  VAr injection upper lim

    ## fudge PMAX a bit if necessary to avoid triggering
    ## dispatchable load constant power factor constraints
    fg[isload(fg), PMAX] = -1e-6
    tg[isload(tg), PMAX] = -1e-6

    ## set all terminal buses to PV (except ref bus)
    refbus = find(ppc['bus'][:, BUS_TYPE] == REF)
    ppc['bus'][dc[:, c.F_BUS], BUS_TYPE] = PV
    ppc['bus'][dc[:, c.T_BUS], BUS_TYPE] = PV
    ppc['bus'][refbus, BUS_TYPE] = REF

    ## append dummy gens
    ppc['gen'] = r_[ppc['gen'], fg, tg]

    ## gencost
    if 'gencost' in ppc and len(ppc['gencost']) > 0:
        ngcr, ngcc = ppc['gencost'].shape   ## dimensions of gencost
        if havecost:         ## user has provided costs
            ndccc = dcc.shape[1]           ## number of dclinecost columns
            ccc = max(r_[ngcc, ndccc])     ## number of columns in new gencost
            if ccc > ngcc:                 ## right zero-pad gencost
                ppc.gencost = c_[ppc['gencost'], zeros(ngcr, ccc-ngcc)]

            ## flip function across vertical axis and append to gencost
            ## (PF for DC line = -PG for dummy gen at "from" bus)
            for k in range(ndc):
                if dcc[k, MODEL] == POLYNOMIAL:
                    nc = dcc[k, NCOST]
                    temp = dcc[k, NCOST + range(nc + 1)]
                    ## flip sign on coefficients of odd terms
                    ## (every other starting with linear term,
                    ##  that is, the next to last one)
#                    temp((nc-1):-2:1) = -temp((nc-1):-2:1)
                    temp[range(nc, 0, -2)] = -temp[range(nc, 0, -2)]
                else:  ## dcc(k, MODEL) == PW_LINEAR
                    nc = dcc[k, NCOST]
                    temp = dcc[k, NCOST + range(2*nc + 1)]
                    ## switch sign on horizontal coordinate
                    xx = -temp[range(0, 2 * nc + 1, 2)]
                    yy =  temp[range(1, 2 * nc + 1, 2)]
                    temp[range(0, 2*nc + 1, 2)] = xx[-1::-1]
                    temp[range(1, 2*nc + 1, 2)] = yy[-1::-1]

                padding = zeros(ccc - NCOST - len(temp))
                gck = c_[dcc[k, :NCOST + 1], temp, padding]

                ## append to gencost
                ppc['gencost'] = r_[ppc['gencost'], gck]

            ## use zero cost on "to" end gen
            tgc = ones((ndc, 1)) * [2, 0, 0, 2, zeros(ccc-4)]
            ppc['gencost'] = c_[ppc['gencost'], tgc]
        else:
            ## use zero cost as default
            dcgc = ones((2 * ndc, 1)) * [2, 0, 0, 2, zeros(ngcc-4)]
            ppc.gencost = r_[ppc['gencost'], dcgc]

    return ppc
Ejemplo n.º 17
0
def makeAvl(baseMVA, gen):
    """Construct linear constraints for constant power factor var loads.

    Constructs parameters for the following linear constraint enforcing a
    constant power factor constraint for dispatchable loads::

         lvl <= Avl * [Pg, Qg] <= uvl

    C{ivl} is the vector of indices of generators representing variable loads.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    ## data dimensions
    ng = gen.shape[0]      ## number of dispatchable injections
    Pg   = gen[:, PG] / baseMVA
    Qg   = gen[:, QG] / baseMVA
    Pmin = gen[:, PMIN] / baseMVA
    Qmin = gen[:, QMIN] / baseMVA
    Qmax = gen[:, QMAX] / baseMVA

    # Find out if any of these "generators" are actually dispatchable loads.
    # (see 'help isload' for details on what constitutes a dispatchable load)
    # Dispatchable loads are modeled as generators with an added constant
    # power factor constraint. The power factor is derived from the original
    # value of Pmin and either Qmin (for inductive loads) or Qmax (for
    # capacitive loads). If both Qmin and Qmax are zero, this implies a unity
    # power factor without the need for an additional constraint.

    ivl = find( isload(gen) & ((Qmin != 0) | (Qmax != 0)) )
    nvl = ivl.shape[0]  ## number of dispatchable loads

    ## at least one of the Q limits must be zero (corresponding to Pmax == 0)
    if any( (Qmin[ivl] != 0) & (Qmax[ivl] != 0) ):
        stderr.write('makeAvl: either Qmin or Qmax must be equal to zero for '
                     'each dispatchable load.\n')

    # Initial values of PG and QG must be consistent with specified power
    # factor This is to prevent a user from unknowingly using a case file which
    # would have defined a different power factor constraint under a previous
    # version which used PG and QG to define the power factor.
    Qlim = (Qmin[ivl] == 0) * Qmax[ivl] + (Qmax[ivl] == 0) * Qmin[ivl]
    if any( abs( Qg[ivl] - Pg[ivl] * Qlim / Pmin[ivl] ) > 1e-6 ):
        stderr.write('makeAvl: For a dispatchable load, PG and QG must be '
                     'consistent with the power factor defined by PMIN and '
                     'the Q limits.\n')

    # make Avl, lvl, uvl, for lvl <= Avl * [Pg Qg] <= uvl
    if nvl > 0:
        xx = Pmin[ivl]
        yy = Qlim
        pftheta = arctan2(yy, xx)
        pc = sin(pftheta)
        qc = -cos(pftheta)
        ii = r_[ arange(nvl), arange(nvl) ]
        jj = r_[ ivl, ivl + ng ]
        Avl = sparse((r_[pc, qc], (ii, jj)), (nvl, 2 * ng))
        lvl = zeros(nvl)
        uvl = lvl
    else:
        Avl = zeros((0, 2*ng))
        lvl = array([])
        uvl = array([])

    return Avl, lvl, uvl, ivl
def t_total_load(quiet=False):
    """Tests for code in C{total_load}.

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

    t_begin(n_tests, quiet)

    ppc = loadcase(join(dirname(__file__), 't_auction_case'))
    ppc['gen'][7, GEN_BUS] = 2    ## multiple d. loads per area, same bus as gen
    ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3])
    ## put it load before gen in matrix

    ppc['gen'] = vstack([ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]])
    ld = find(isload(ppc['gen']))
    a = [None] * 3
    lda = [None] * 3
    for k in range(3):
        a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1)  ## buses in area k
        tmp = find( in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k]) )
        lda[k] = ld[tmp]                       ## disp loads in area k

    area = [None] * 3
    for k in range(3):
        area[k] = {'fixed': {}, 'disp': {}, 'both': {}}
        area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD])
        area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD])
        area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN])
        area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN])
        area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX])
        area[k]['disp']['q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax']
        area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p']
        area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q']

    total = {'fixed': {}, 'disp': {}, 'both': {}}
    total['fixed']['p'] = sum(ppc['bus'][:, PD])
    total['fixed']['q'] = sum(ppc['bus'][:, QD])
    total['disp']['p'] = -sum(ppc['gen'][ld, PMIN])
    total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN])
    total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX])
    total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax']
    total['both']['p'] = total['fixed']['p'] + total['disp']['p']
    total['both']['q'] = total['fixed']['q'] + total['disp']['q']

    ##-----  all load  -----
    t = 'Pd, _  = total_load(bus) : '
    Pd, _ = total_load(ppc['bus'])
    t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus) : '
    Pd, Qd = total_load(ppc['bus'])
    t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen) : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'])
    t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen) : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'])
    t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, None, \'all\') : '
    Pd, _ = total_load(ppc['bus'], None, 'all')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, None, \'all\') : '
    Pd, Qd = total_load(ppc['bus'], None, 'all')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['fixed']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['both']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\', \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\', \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['both']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\', \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\', \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['fixed']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE')
    t_is(Pd, total['disp']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE')
    t_is(Pd, total['disp']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['disp']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, None, \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'BOTH')
    t_is(Pd, r_[area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, None, \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'BOTH')
    t_is(Pd, [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, None, \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'FIXED')
    t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, None, \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'FIXED')
    t_is(Pd, [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, None, \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE')
    t_is(Pd, [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, None, \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE')
    t_is(Pd, [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[0]['disp']['q'], area[1]['disp']['q'], area[2]['disp']['q']], 12, [t, 'Qd'])

    ##-----  explicit single load zone  -----
    nb = ppc['bus'].shape[0]
    load_zone = zeros(nb, int)
    k = find(ppc['bus'][:, BUS_AREA] == 2)    ## area 2
    load_zone[k] = 1
    t = 'Pd, _  = total_load(bus, gen, load_zone1, \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd'])
    t_is(Qd, area[1]['both']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone1, \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd'])
    t_is(Qd, area[1]['fixed']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd'])
    t_is(Qd, area[1]['disp']['q'], 12, [t, 'Qd'])

    ##-----  explicit multiple load zone  -----
    load_zone = zeros(nb, int)
    k = find(ppc['bus'][:, BUS_AREA] == 3)    ## area 3
    load_zone[k] = 1
    k = find(ppc['bus'][:, BUS_AREA] == 1)    ## area 1
    load_zone[k] = 2
    t = 'Pd, _  = total_load(bus, gen, load_zone2, \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[2]['both']['q'], area[0]['both']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone2, \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[2]['fixed']['q'], area[0]['fixed']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[2]['disp']['q'], area[0]['disp']['q']], 12, [t, 'Qd'])

    t_end()
Ejemplo n.º 19
0
def t_runmarket(quiet=False):
    """Tests for code in C{runmkt}, C{smartmkt} and C{auction}.

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

    t_begin(n_tests, quiet)

    try:
        from pypower.extras.smartmarket import runmarket
    except ImportError:
        t_skip(n_tests, 'smartmarket code not available')
        t_end
        return

    ppc = loadcase('t_auction_case')

    ppopt = ppoption(OPF_ALG=560, OUT_ALL_LIM=1, OUT_BRANCH=0, OUT_SYS_SUM=0)
    ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=1)
    #ppopt = ppoption(ppopt, OUT_GEN=1, OUT_BRANCH=0, OUT_SYS_SUM=0)

    offers = {'P': {}, 'Q': {}}
    bids = {'P': {}, 'Q': {}}

    offers['P']['qty'] = array([[12, 24, 24], [12, 24, 24], [12, 24, 24],
                                [12, 24, 24], [12, 24, 24], [12, 24, 24]])
    offers['P']['prc'] = array([[20, 50, 60], [20, 40, 70], [20, 42, 80],
                                [20, 44, 90], [20, 46, 75], [20, 48, 60]])
    bids['P']['qty'] = array([[10, 10, 10], [10, 10, 10], [10, 10, 10]])
    bids['P']['prc'] = array([
        [100, 70, 60],
        #         [100, 64.3, 20],
        #         [100, 30.64545, 0],
        [100, 50, 20],
        [100, 60, 50]
    ])

    offers['Q']['qty'] = [60, 60, 60, 60, 60, 60, 0, 0, 0]
    offers['Q']['prc'] = [0, 0, 0, 0, 0, 3, 0, 0, 0]
    bids.Q['qty'] = [15, 15, 15, 15, 15, 15, 15, 12, 7.5]
    #     bids.Q['prc'] = [ 0, 0, 0, 0, 0, 0, 0, 83.9056, 0 ]
    bids.Q['prc'] = [0, 0, 0, 0, 0, 0, 0, 20, 0]

    t = 'marginal Q offer, marginal PQ bid, auction_type = 5'
    mkt = {'auction_type': 5, 't': [], 'u0': [], 'lim': []}
    r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt)
    co5 = co.copy()
    cb5 = cb.copy()

    #     [ co['P']['qty'] co['P']['prc'] ]
    #     [ cb['P']['qty'] cb['P']['prc'] ]
    #     [ co['Q']['qty'] co['Q']['prc'] ]
    #     [ cb['Q']['qty'] cb['Q']['prc'] ]

    i2e = r['bus'][:, BUS_I]
    e2i = sparse((max(i2e), 1))
    e2i[i2e] = list(range(r['bus'].size))
    G = find(isload(r['gen']) == 0)  ## real generators
    L = find(isload(r['gen']))  ## dispatchable loads
    Gbus = e2i[r['gen'][G, GEN_BUS]]
    Lbus = e2i[r['gen'][L, GEN_BUS]]

    t_is(co['P']['qty'],
         ones((6, 1)) * [12, 24, 0], 2, [t, ' : gen P quantities'])
    t_is(co['P']['prc'][0, :], 50.1578, 3, [t, ' : gen 1 P prices'])
    t_is(cb['P']['qty'], [[10, 10, 10], [10, 0.196, 0], [10, 10, 0]], 2,
         [t, ' : load P quantities'])
    t_is(cb['P']['prc'][1, :], 56.9853, 4, [t, ' : load 2 P price'])
    t_is(co['P']['prc'][:, 0], r['bus'][Gbus, LAM_P], 8,
         [t, ' : gen P prices'])
    t_is(cb['P']['prc'][:, 0], r['bus'][Lbus, LAM_P], 8,
         [t, ' : load P prices'])

    t_is(co['Q']['qty'],
         [4.2722, 11.3723, 14.1472, 22.8939, 36.7886, 12.3375, 0, 0, 0], 2,
         [t, ' : Q offer quantities'])
    t_is(co['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4,
         [t, ' : Q offer prices'])
    t_is(cb['Q']['qty'], [0, 0, 0, 0, 0, 0, 15, 4.0785, 5], 2,
         [t, ' : Q bid quantities'])
    t_is(cb['Q']['prc'], [0, 0, 0, 0, 0, 3, 0.4861, 2.5367, 1.3763], 4,
         [t, ' : Q bid prices'])
    t_is(co['Q']['prc'], r['bus'][[Gbus, Lbus], LAM_Q], 8,
         [t, ' : Q offer prices'])
    t_is(cb['Q']['prc'], co['Q']['prc'], 8, [t, ' : Q bid prices'])

    t = 'marginal Q offer, marginal PQ bid, auction_type = 0'
    mkt['auction_type'] = 0
    r, co, cb, _, _, _, _ = runmarket(ppc, offers, bids, mkt, ppopt)
    t_is(co['P']['qty'], co5['P']['qty'], 8, [t, ' : gen P quantities'])
    t_is(cb['P']['qty'], cb5['P']['qty'], 8, [t, ' : load P quantities'])
    t_is(co['P']['prc'], offers['P']['prc'], 8, [t, ' : gen P prices'])
    t_is(cb['P']['prc'], bids['P']['prc'], 8, [t, ' : load P prices'])

    t_is(co['Q']['qty'], co5['Q']['qty'], 8, [t, ' : gen Q quantities'])
    t_is(cb['Q']['qty'], cb5['Q']['qty'], 8, [t, ' : load Q quantities'])
    t_is(co['Q']['prc'], offers['Q']['prc'], 8, [t, ' : gen Q prices'])
    t_is(cb['Q']['prc'], bids['Q']['prc'], 8, [t, ' : load Q prices'])

    t_end
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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()
Ejemplo n.º 22
0
def t_total_load(quiet=False):
    """Tests for code in C{total_load}.

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

    t_begin(n_tests, quiet)

    ppc = loadcase(join(dirname(__file__), 't_auction_case'))
    ppc['gen'][7, GEN_BUS] = 2  ## multiple d. loads per area, same bus as gen
    ppc['gen'][7, [QG, QMIN, QMAX]] = array([3, 0, 3])
    ## put it load before gen in matrix

    ppc['gen'] = vstack(
        [ppc['gen'][7, :], ppc['gen'][:7, :], ppc['gen'][8, :]])
    ld = find(isload(ppc['gen']))
    a = [None] * 3
    lda = [None] * 3
    for k in range(3):
        a[k] = find(ppc['bus'][:, BUS_AREA] == k + 1)  ## buses in area k
        tmp = find(in1d(ppc['gen'][ld, GEN_BUS] - 1, a[k]))
        lda[k] = ld[tmp]  ## disp loads in area k

    area = [None] * 3
    for k in range(3):
        area[k] = {'fixed': {}, 'disp': {}, 'both': {}}
        area[k]['fixed']['p'] = sum(ppc['bus'][a[k], PD])
        area[k]['fixed']['q'] = sum(ppc['bus'][a[k], QD])
        area[k]['disp']['p'] = -sum(ppc['gen'][lda[k], PMIN])
        area[k]['disp']['qmin'] = -sum(ppc['gen'][lda[k], QMIN])
        area[k]['disp']['qmax'] = -sum(ppc['gen'][lda[k], QMAX])
        area[k]['disp'][
            'q'] = area[k]['disp']['qmin'] + area[k]['disp']['qmax']
        area[k]['both']['p'] = area[k]['fixed']['p'] + area[k]['disp']['p']
        area[k]['both']['q'] = area[k]['fixed']['q'] + area[k]['disp']['q']

    total = {'fixed': {}, 'disp': {}, 'both': {}}
    total['fixed']['p'] = sum(ppc['bus'][:, PD])
    total['fixed']['q'] = sum(ppc['bus'][:, QD])
    total['disp']['p'] = -sum(ppc['gen'][ld, PMIN])
    total['disp']['qmin'] = -sum(ppc['gen'][ld, QMIN])
    total['disp']['qmax'] = -sum(ppc['gen'][ld, QMAX])
    total['disp']['q'] = total['disp']['qmin'] + total['disp']['qmax']
    total['both']['p'] = total['fixed']['p'] + total['disp']['p']
    total['both']['q'] = total['fixed']['q'] + total['disp']['q']

    ##-----  all load  -----
    t = 'Pd, _  = total_load(bus) : '
    Pd, _ = total_load(ppc['bus'])
    t_is(Pd,
         [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']],
         12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus) : '
    Pd, Qd = total_load(ppc['bus'])
    t_is(Pd,
         [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']],
         12, [t, 'Pd'])
    t_is(Qd,
         [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']],
         12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen) : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'])
    t_is(Pd,
         [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']],
         12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen) : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'])
    t_is(Pd,
         [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']],
         12, [t, 'Pd'])
    t_is(Qd,
         [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']],
         12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, None, \'all\') : '
    Pd, _ = total_load(ppc['bus'], None, 'all')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, None, \'all\') : '
    Pd, Qd = total_load(ppc['bus'], None, 'all')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['fixed']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['both']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\', \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\', \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'BOTH')
    t_is(Pd, total['both']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['both']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\', \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\', \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'FIXED')
    t_is(Pd, total['fixed']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['fixed']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE')
    t_is(Pd, total['disp']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, \'all\', \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], 'all', 'DISPATCHABLE')
    t_is(Pd, total['disp']['p'], 12, [t, 'Pd'])
    t_is(Qd, total['disp']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, None, \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'BOTH')
    t_is(Pd, r_[area[0]['both']['p'], area[1]['both']['p'],
                area[2]['both']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, None, \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'BOTH')
    t_is(Pd,
         [area[0]['both']['p'], area[1]['both']['p'], area[2]['both']['p']],
         12, [t, 'Pd'])
    t_is(Qd,
         [area[0]['both']['q'], area[1]['both']['q'], area[2]['both']['q']],
         12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, None, \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'FIXED')
    t_is(Pd,
         [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']],
         12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, None, \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'FIXED')
    t_is(Pd,
         [area[0]['fixed']['p'], area[1]['fixed']['p'], area[2]['fixed']['p']],
         12, [t, 'Pd'])
    t_is(Qd,
         [area[0]['fixed']['q'], area[1]['fixed']['q'], area[2]['fixed']['q']],
         12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, None, \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE')
    t_is(Pd,
         [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']],
         12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, None, \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], None, 'DISPATCHABLE')
    t_is(Pd,
         [area[0]['disp']['p'], area[1]['disp']['p'], area[2]['disp']['p']],
         12, [t, 'Pd'])
    t_is(Qd,
         [area[0]['disp']['q'], area[1]['disp']['q'], area[2]['disp']['q']],
         12, [t, 'Qd'])

    ##-----  explicit single load zone  -----
    nb = ppc['bus'].shape[0]
    load_zone = zeros(nb, int)
    k = find(ppc['bus'][:, BUS_AREA] == 2)  ## area 2
    load_zone[k] = 1
    t = 'Pd, _  = total_load(bus, gen, load_zone1, \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, area[1]['both']['p'], 12, [t, 'Pd'])
    t_is(Qd, area[1]['both']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone1, \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, area[1]['fixed']['p'], 12, [t, 'Pd'])
    t_is(Qd, area[1]['fixed']['q'], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone1, \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, area[1]['disp']['p'], 12, [t, 'Pd'])
    t_is(Qd, area[1]['disp']['q'], 12, [t, 'Qd'])

    ##-----  explicit multiple load zone  -----
    load_zone = zeros(nb, int)
    k = find(ppc['bus'][:, BUS_AREA] == 3)  ## area 3
    load_zone[k] = 1
    k = find(ppc['bus'][:, BUS_AREA] == 1)  ## area 1
    load_zone[k] = 2
    t = 'Pd, _  = total_load(bus, gen, load_zone2, \'BOTH\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'BOTH\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'BOTH')
    t_is(Pd, [area[2]['both']['p'], area[0]['both']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[2]['both']['q'], area[0]['both']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone2, \'FIXED\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'FIXED\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'FIXED')
    t_is(Pd, [area[2]['fixed']['p'], area[0]['fixed']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[2]['fixed']['q'], area[0]['fixed']['q']], 12, [t, 'Qd'])

    t = 'Pd, _  = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : '
    Pd, _ = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd'])

    t = 'Pd, Qd = total_load(bus, gen, load_zone2, \'DISPATCHABLE\') : '
    Pd, Qd = total_load(ppc['bus'], ppc['gen'], load_zone, 'DISPATCHABLE')
    t_is(Pd, [area[2]['disp']['p'], area[0]['disp']['p']], 12, [t, 'Pd'])
    t_is(Qd, [area[2]['disp']['q'], area[0]['disp']['q']], 12, [t, 'Qd'])

    t_end()