示例#1
0
    def __init__(self, paramfile):
        for row in paramfile:

            if row[0]=='BIAS_COMBINE': self.BIAS_COMBINE = row[1]
            if row[0]=='COMP_COMBINE': self.COMP_COMBINE = row[1]
            if row[0]=='FLAT_COMBINE': self.FLAT_COMBINE = row[1]
            if row[0]=='FIBER_TRACE': self.FIBER_TRACE = row[1]
            if row[0]=='BIAS_SUBTRACT': self.BIAS_SUBTRACT = row[1]
            if row[0]=='LAMBDA_SOLVE': self.LAMBDA_SOLVE = row[1]
            if row[0]=='COSMIC_RAYS': self.COSMIC_RAYS = row[1]
            if row[0]=='SKY_SUBTRACT': self.SKY_SUBTRACT = row[1]
            if row[0]=='WRITE_SPECTRA': self.WRITE_SPECTRA = row[1]
            
            if row[0]=='FIBERS_TOTAL': self.FIBERS_TOTAL = int(row[1])
            if row[0]=='FIBERS_EXCLUDE':
                fibs = np.array( [ int(i) for i in row[1].split(',') ] )
                fibs.sort()
                fibs = fibs[ np.find( 0<fibs ) ]
                fibs = fibs[ np.find( fibs<self.FIBERS_TOTAL+1 ) ]
                self.FIBERS_EXCLUDE = fibs
            if row[0]=='FIBER_WIDTH': self.FIBER_WIDTH = int(row[1])
            if row[0]=='FIBER_SEP': self.FIBER_SEP = int(row[1])
            if row[0]=='LO_BUFFER': self.LO_BUFFER = int(row[1])
            if row[0]=='HI_BUFFER': self.HI_BUFFER = int(row[1])
            if row[0]=='LINE_LIST': self.LINE_LIST = row[1]
            if row[0]=='COMP_HEADER': self.COMP_HEADER = row[1]
            if row[0]=='COMP_NAME': self.COMP_NAME = row[1]
            if row[0]=='POLYFIT_ORDER': self.POLYFIT_ORDER = int(row[1])
            if row[0]=='CR_SCAN_DX': self.CR_SCAN_DX = int(row[1])
示例#2
0
def bustypes(bus, gen):
    """Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).

    Generators with "out-of-service" status are treated as L{PQ} buses with
    zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
    and C{gen} have been converted to use internal consecutive bus numbering.

    @param bus: bus data
    @param gen: generator data
    @return: index lists of each bus type

    @author: Ray Zimmerman (PSERC Cornell)
    """
    # get generator status
    nb = bus.shape[0]
    ng = gen.shape[0]
    # gen connection matrix, element i, j is 1 if, generator j at bus i is ON
    Cg = sparse((gen[:, GEN_STATUS] > 0, (gen[:, GEN_BUS], range(ng))),
                (nb, ng))
    # number of generators at each bus that are ON
    bus_gen_status = (Cg * ones(ng, int)).astype(bool)

    # form index lists for slack, PV, and PQ buses
    ref = find((bus[:, BUS_TYPE] == REF) & bus_gen_status)  # ref bus index
    pv = find((bus[:, BUS_TYPE] == PV) & bus_gen_status)  # PV bus indices
    pq = find((bus[:, BUS_TYPE] == PQ) | ~bus_gen_status)  # PQ bus indices

    # pick a new reference bus if for some reason there is none (may have been
    # shut down)
    if len(ref) == 0:
        ref = pv[0]  # use the first PV bus
        pv = pv[1:]  # take it off PV list

    return ref, pv, pq
示例#3
0
def bustypes(bus, gen):
    """Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).

    Generators with "out-of-service" status are treated as L{PQ} buses with
    zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
    and C{gen} have been converted to use internal consecutive bus numbering.

    @param bus: bus data
    @param gen: generator data
    @return: index lists of each bus type

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln

    changes by Uni Kassel (Florian Schaefer): If new ref bus is chosen -> Init as numpy array
    """
    # get generator status
    #    nb = bus.shape[0]
    #    ng = gen.shape[0]
    # gen connection matrix, element i, j is 1 if, generator j at bus i is ON
    #Cg = sparse((gen[:, GEN_STATUS] > 0,
    #                 (gen[:, GEN_BUS], range(ng))), (nb, ng))
    # number of generators at each bus that are ON
    #bus_gen_status = (Cg * ones(ng, int)).astype(bool)

    # form index lists for slack, PV, and PQ buses
    ref = find((bus[:, BUS_TYPE] == REF))  # ref bus index
    pv = find((bus[:, BUS_TYPE] == PV))  # PV bus indices
    pq = find((bus[:, BUS_TYPE] == PQ))  # PQ bus indices
    return ref, pv, pq
示例#4
0
def makePTDF(baseMVA, bus, branch, slack=None):
    """Builds the DC PTDF matrix for a given choice of slack.

    Returns the DC PTDF matrix for a given choice of slack. The matrix is
    C{nbr x nb}, where C{nbr} is the number of branches and C{nb} is the
    number of buses. The C{slack} can be a scalar (single slack bus) or an
    C{nb x 1} column vector of weights specifying the proportion of the
    slack taken up at each bus. If the C{slack} is not specified the
    reference bus is used by default.

    For convenience, C{slack} can also be an C{nb x nb} matrix, where each
    column specifies how the slack should be handled for injections
    at that bus.

    @see: L{makeLODF}

    @author: Ray Zimmerman (PSERC Cornell)
    """
    ## use reference bus for slack by default
    if slack is None:
        slack = find(bus[:, BUS_TYPE] == REF)
        slack = slack[0]

    ## set the slack bus to be used to compute initial PTDF
    if isscalar(slack):
        slack_bus = slack
    else:
        slack_bus = 0      ## use bus 1 for temp slack bus

    nb = bus.shape[0]
    nbr = branch.shape[0]
    noref = arange(1, nb)      ## use bus 1 for voltage angle reference
    noslack = find(arange(nb) != slack_bus)

    ## check that bus numbers are equal to indices to bus (one set of bus numbers)
    if any(bus[:, BUS_I] != arange(nb)):
        stderr.write('makePTDF: buses must be numbered consecutively')

    ## compute PTDF for single slack_bus
    Bbus, Bf, _, _ = makeBdc(baseMVA, bus, branch)
    Bbus, Bf = Bbus.todense(), Bf.todense()
    H = zeros((nbr, nb))
    H[:, noslack] = solve( Bbus[ix_(noslack, noref)].T, Bf[:, noref].T ).T
    #             = Bf[:, noref] * inv(Bbus[ix_(noslack, noref)])

    ## distribute slack, if requested
    if not isscalar(slack):
        if len(slack.shape) == 1:  ## slack is a vector of weights
            slack = slack / sum(slack)   ## normalize weights

            ## conceptually, we want to do ...
            ##    H = H * (eye(nb, nb) - slack * ones((1, nb)))
            ## ... we just do it more efficiently
            v = dot(H, slack)
            for k in range(nb):
                H[:, k] = H[:, k] - v
        else:
            H = dot(H, slack)

    return H
def ppci_to_pfsoln(ppci, options):
    internal = ppci["internal"]
    if options["only_v_results"]:
        # time series relevant hack which ONLY saves V from ppci
        _update_v(internal["bus"], internal["V"])
        return internal["bus"], internal["gen"], internal["branch"]
    else:
        # reads values from internal ppci storage to bus, gen, branch and returns it
        if options['distributed_slack']:
            # consider buses with non-zero slack weights as if they were slack buses,
            # and gens with non-zero slack weights as if they were reference machines
            # this way, the function pfsoln will extract results for distributed slack gens, too
            # also, the function pfsoln will extract results for the PQ buses for xwards
            gens_with_slack_weights = find(internal["gen"][:, SL_FAC] != 0)
            # gen_buses_with_slack_weights = internal["gen"][gens_with_slack_weights, GEN_BUS].astype(int32)
            buses_with_slack_weights = internal["bus"][find(
                internal["bus"][:, SL_FAC_BUS] != 0), BUS_I].astype(int32)
            # buses_with_slack_weights = union1d(gen_buses_with_slack_weights, buses_with_slack_weights)
            ref = union1d(internal["ref"], buses_with_slack_weights)
            ref_gens = union1d(internal["ref_gens"], gens_with_slack_weights)
        else:
            ref = internal["ref"]
            ref_gens = internal["ref_gens"]

        _, pfsoln = _get_numba_functions(ppci, options)
        result_pfsoln = pfsoln(internal["baseMVA"], internal["bus"],
                               internal["gen"], internal["branch"],
                               internal["Ybus"], internal["Yf"],
                               internal["Yt"], internal["V"], ref, ref_gens)
        return result_pfsoln
示例#6
0
def bustypes(bus, gen):
    """Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).

    Generators with "out-of-service" status are treated as L{PQ} buses with
    zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
    and C{gen} have been converted to use internal consecutive bus numbering.

    @param bus: bus data
    @param gen: generator data
    @return: index lists of each bus type

    @author: Ray Zimmerman (PSERC Cornell)
    """
    # get generator status
    nb = bus.shape[0]
    ng = gen.shape[0]
    # gen connection matrix, element i, j is 1 if, generator j at bus i is ON
    Cg = sparse((gen[:, GEN_STATUS] > 0,
                 (gen[:, GEN_BUS], range(ng))), (nb, ng))
    # number of generators at each bus that are ON
    bus_gen_status = (Cg * ones(ng, int)).astype(bool)

    # form index lists for slack, PV, and PQ buses
    ref = find((bus[:, BUS_TYPE] == REF) & bus_gen_status) # ref bus index
    pv  = find((bus[:, BUS_TYPE] == PV)  & bus_gen_status) # PV bus indices
    pq  = find((bus[:, BUS_TYPE] == PQ) | ~bus_gen_status) # PQ bus indices

    # pick a new reference bus if for some reason there is none (may have been
    # shut down)
    if len(ref) == 0:
        ref = pv[0]      # use the first PV bus
        pv = pv[1:]      # take it off PV list

    return ref, pv, pq
示例#7
0
def sumAnyNBinom(p, anyN=1):
    """Returns probability of a positive outcome given that 
    a positive outcome requires at least anyN events,
    and given that the independent probability of each event is in vector p.

    Parameters
    ----------
    p : list or 1darray
        Vector of probabilities of each independent event.
    anyN : int
        Minimum number of events required to be considered a positive outcome.

    Returns
    -------
    tot : float
        Overall probability of a positive outcome."""
    if isinstance(p, list):
        p = np.asarray(p)
    n = len(p)
    tmp = np.zeros(n)
    tot = np.zeros(2**n)
    for eventi, event in enumerate(itertools.product(*tuple([[0, 1]] * n))):
        event = np.array(event)
        if np.sum(event) >= anyN:
            tmp[np.find(event == 1)] = p[np.find(event == 1)]
            tmp[np.find(event == 0)] = 1 - p[np.find(event == 0)]
            tot[eventi] = np.prod(tmp)
    return tot.sum()
示例#8
0
    def _sys_event(self, C):
        sysdef = self.sysdef
        row, col = C.shape

        if self.systype.lower() == "series":
            self.cutset = 1 - np.prod(np.ones((row, col)) - C, axis=1, dtype=int)
            ncutsets = []
        elif self.systype.lower() == "parallel":
            self.cutset = np.prod(C, axis=1, dtype=int)
            ncutsets = []
        else:
            if self.sysdef[1].lower() == "link":
                self.sysdef = -self.sysdef
            self.sysdef[0] = np.hstack((0, self.sysdef[0], 0))
            sysnonzero = np.find(self.sysdef[0] != 0)[0]
            syszero = np.find(self.sysdef[0] == 0)[0]
            int1 = syszero - np.hstack((0, syszero[:-1]))
            sizeCutSets = int1[int1 > 1] - 1
            ncutsets = sizeCutSets.shape[0]
            for i in xrange(ncutsets):
                cCutSet = np.ones(row, 1)
                for j in xrange(sizeCutSets[i]):
                    comp = self.sysdef[0][sysnonzero[np.sum(sizeCutSets[:i]) + j]]
                    if comp < 0:
                        cCutSet = cCutSet * (np.ones((row, 1)) - C.T[:, abs(comp)])
                    else:
                        cCutSet = cCutSet * C.T[:, comp]
                cCutSets[:, i] = cCutSet
            self.cutset = np.ones(row, 1) - np.prod(np.ones(row, ncutsets) - cCutSets, axis=1)
示例#9
0
文件: tdem.py 项目: wk1984/gimli
def rhoa( snd, cal=260e-9, corrramp=True ):
    ''' compute apparent resistivity from sounding '''
    Tx = np.prod( [float(a) for a in snd['LOOP_SIZE'].split()] )
    if 'COIL_SIZE' in snd:
        Rx = snd['COIL_SIZE']
    else:
        Rx = Tx
    
    v = snd['VOLTAGE']
    istart, istop = 0, len(v) # default: take all
    mav = np.find( v == max(v) )
    if len(mav) > 1: #several equal big ones: start after
        istart = max(mav)+1

    if min(v) < 0.0: # negative values: stop at first
        istop = min( np.find( v < 0.0 ) )
    
    v = v[istart:istop]
    dv = snd['ST_DEV'][istart:istop] #/ snd['CURRENT']
    t = snd['TIME'][istart:istop]
    if corrramp and 'RAMP_TIME' in snd: 
        t = t - snd['RAMP_TIME']
    
    if Rx == 1: # apparently B-field
        rhoa = rhoafromB( v * cal, t, Tx )
    else:
        rhoa = rhoafromU( v, t, Tx, Rx )

    rhoaerr = dv / v * (2./3.)
    return rhoa, t, rhoaerr
示例#10
0
def bustypes(bus, gen, Sbus):
    """
    Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).

    Generators with "out-of-service" status are treated as L{PQ} buses with
    zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
    and C{gen} have been converted to use internal consecutive bus numbering.

    @param bus: bus data
    @param gen: generator data
    @return: index lists of each bus type

    @author: Ray Zimmerman (PSERC Cornell)
    """
    # flag to indicate that it is impossible to solve the grid
    the_grid_is_disabled = False

    # get generator status
    nb = bus.shape[0]
    ng = gen.shape[0]
    # gen connection matrix, element i, j is 1 if, generator j at bus i is ON
    Cg = sparse((gen[:, GEN_STATUS] > 0, (gen[:, GEN_BUS], range(ng))),
                (nb, ng))
    # number of generators at each bus that are ON
    bus_gen_status = (Cg * ones(ng, int)).astype(bool)

    # form index lists for slack, PV, and PQ buses
    ref = find((bus[:, BUS_TYPE] == REF) & bus_gen_status)  # ref bus index
    pv = find((bus[:, BUS_TYPE] == PV) & bus_gen_status)  # PV bus indices
    pq = find((bus[:, BUS_TYPE] == PQ) | ~bus_gen_status)  # PQ bus indices

    # pick a new reference bus if for some reason there is none (may have been
    # shut down)
    if len(ref) == 0:
        if len(pv) > 0:
            ref = [pv[0]]  # use the first PV bus
            pv = pv[1:]  # take it off PV list
        else:  # look for positive power injections to take the largest as the slack
            positive_power_injections = Sbus.real[where(Sbus.real > 0)[0]]
            if len(positive_power_injections) > 0:
                idx = where(Sbus.real == max(positive_power_injections))[0]
                if len(idx) == 1:
                    ref = idx
                    i = where(pq == idx[0])[0][0]
                    pq = delete(pq, i)
                else:
                    warn('It was not possible to find a slack bus')
                    the_grid_is_disabled = True
            else:
                warn('It was not possible to find a slack bus')
                the_grid_is_disabled = True

    # create the types array
    types = zeros(nb)
    types[ref] = 3
    types[pv] = 2
    types[pq] = 1

    return ref, pv, pq, types, the_grid_is_disabled
示例#11
0
def bustypes(bus, gen, Sbus):
    """
    Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).

    Generators with "out-of-service" status are treated as L{PQ} buses with
    zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
    and C{gen} have been converted to use internal consecutive bus numbering.

    @param bus: bus data
    @param gen: generator data
    @return: index lists of each bus type

    @author: Ray Zimmerman (PSERC Cornell)
    """
    # flag to indicate that it is impossible to solve the grid
    the_grid_is_disabled = False

    # get generator status
    nb = bus.shape[0]
    ng = gen.shape[0]
    # gen connection matrix, element i, j is 1 if, generator j at bus i is ON
    Cg = sparse((gen[:, GEN_STATUS] > 0,
                 (gen[:, GEN_BUS], range(ng))), (nb, ng))
    # number of generators at each bus that are ON
    bus_gen_status = (Cg * ones(ng, int)).astype(bool)

    # form index lists for slack, PV, and PQ buses
    ref = find((bus[:, BUS_TYPE] == REF) & bus_gen_status)  # ref bus index
    pv = find((bus[:, BUS_TYPE] == PV) & bus_gen_status)  # PV bus indices
    pq = find((bus[:, BUS_TYPE] == PQ) | ~bus_gen_status)  # PQ bus indices

    # pick a new reference bus if for some reason there is none (may have been
    # shut down)
    if len(ref) == 0:
        if len(pv) > 0:
            ref = [pv[0]]      # use the first PV bus
            pv = pv[1:]      # take it off PV list
        else:   # look for positive power injections to take the largest as the slack
            positive_power_injections = Sbus.real[where(Sbus.real > 0)[0]]
            if len(positive_power_injections) > 0:
                idx = where(Sbus.real == max(positive_power_injections))[0]
                if len(idx) == 1:
                    ref = idx
                    i = where(pq == idx[0])[0][0]
                    pq = delete(pq, i)
                else:
                    warn('It was not possible to find a slack bus')
                    the_grid_is_disabled = True
            else:
                warn('It was not possible to find a slack bus')
                the_grid_is_disabled = True

    # create the types array
    types = zeros(nb)
    types[ref] = 3
    types[pv] = 2
    types[pq] = 1

    return ref, pv, pq, types, the_grid_is_disabled
示例#12
0
def userfcn_reserves_ext2int(ppc, *args):
    """This is the 'ext2int' stage userfcn callback that prepares the input
    data for the formulation stage. It expects to find a 'reserves' field
    in ppc as described above. The optional args are not currently used.
    """
    ## initialize some things
    r = ppc['reserves']
    o = ppc['order']
    ng0 = o['ext']['gen'].shape[0]  ## number of original gens (+ disp loads)
    nrz = r['req'].shape[0]         ## number of reserve zones
    if nrz > 1:
        ppc['reserves']['rgens'] = any(r['zones'], 0)  ## mask of gens available to provide reserves
    else:
        ppc['reserves']['rgens'] = r['zones']

    igr = find(ppc['reserves']['rgens']) ## indices of gens available to provide reserves
    ngr = len(igr)              ## number of gens available to provide reserves

    ## check data for consistent dimensions
    if r['zones'].shape[0] != nrz:
        stderr.write('userfcn_reserves_ext2int: the number of rows in ppc[\'reserves\'][\'req\'] (%d) and ppc[\'reserves\'][\'zones\'] (%d) must match\n' % (nrz, r['zones'].shape[0]))

    if (r['cost'].shape[0] != ng0) & (r['cost'].shape[0] != ngr):
        stderr.write('userfcn_reserves_ext2int: the number of rows in ppc[\'reserves\'][\'cost\'] (%d) must equal the total number of generators (%d) or the number of generators able to provide reserves (%d)\n' % (r['cost'].shape[0], ng0, ngr))

    if 'qty' in r:
        if r['qty'].shape[0] != r['cost'].shape[0]:
            stderr.write('userfcn_reserves_ext2int: ppc[\'reserves\'][\'cost\'] (%d x 1) and ppc[\'reserves\'][\'qty\'] (%d x 1) must be the same dimension\n' % (r['cost'].shape[0], r['qty'].shape[0]))


    ## convert both cost and qty from ngr x 1 to full ng x 1 vectors if necessary
    if r['cost'].shape[0] < ng0:
        if 'original' not in ppc['reserves']:
            ppc['reserves']['original'] = {}
        ppc['reserves']['original']['cost'] = r['cost'].copy()    ## save original
        cost = zeros(ng0)
        cost[igr] = r['cost']
        ppc['reserves']['cost'] = cost
        if 'qty' in r:
            ppc['reserves']['original']['qty'] = r['qty'].copy()  ## save original
            qty = zeros(ng0)
            qty[igr] = r['qty']
            ppc['reserves']['qty'] = qty

    ##-----  convert stuff to internal indexing  -----
    ## convert all reserve parameters (zones, costs, qty, rgens)
    if 'qty' in r:
        ppc = e2i_field(ppc, ['reserves', 'qty'], 'gen')

    ppc = e2i_field(ppc, ['reserves', 'cost'], 'gen')
    ppc = e2i_field(ppc, ['reserves', 'zones'], 'gen', 1)
    ppc = e2i_field(ppc, ['reserves', 'rgens'], 'gen', 1)

    ## save indices of gens available to provide reserves
    ppc['order']['ext']['reserves']['igr'] = igr               ## external indexing
    ppc['reserves']['igr'] = find(ppc['reserves']['rgens'])    ## internal indexing

    return ppc
示例#13
0
def getHNR(y, Fs, F0, Nfreqs):
    print('holla')
    NBins = len(y)
    N0 = round(Fs / F0)
    N0_delta = round(N0 * 0.1)

    y = [x * z for x, z in zip(np.hamming(len(y)), y)]
    fftY = np.fft(y, NBins)
    aY = np.log10(abs(fftY))
    ay = np.ifft(aY)

    peakinx = np.zeros(np.floor(len(y)) / 2 / N0)
    for k in range(1, len(peakinx)):
        ayseg = ay[(k * N0 - N0_delta):(k * N0 + N0_delta)]
        val, inx = max(
            abs(ayseg))  # MAX does not behave the same - doesn't return inx??
        peakinx[k] = inx + (k * N0) - N0_delta - 1

        s_ayseg = np.sign(np.diff(ayseg))

        l_inx = inx - np.find(
            (np.sign(s_ayseg[inx - 1:-1:1]) != np.sign(inx)))[0] + 1
        r_inx = inx + np.find(np.sign(s_ayseg[inx + 1:]) == np.sign(inx))[0]

        l_inx = l_inx + k * N0 - N0_delta - 1
        r_inx = r_inx + k * N0 - N0_delta - 1

        for num in range(l_inx, r_inx):
            ay[num] = 0

    midL = round(len(y) / 2) + 1
    ay[midL:] = ay[(midL - 1):-1:(midL - 1 - (len(ay) - midL))]

    Nap = np.real(np.fft(ay))
    N = Nap  # ???? why?
    Ha = aY - Nap  # change these names ffs

    Hdelta = F0 / Fs * len(y)
    for f in [
            num + 0.0001 for num in range(Hdelta, round(len(y) / 2), Hdelta)
    ]:
        fstart = np.ceil(f - Hdelta)
        Bdf = abs(min(Ha[fstart:round(f)]))
        N[fstart:round(f)] = N[fstart:round(f)] - Bdf

    H = aY - N
    n = np.zeros(len(Nfreqs))

    for k in range(1, len(Nfreqs)):
        Ef = round(Nfreqs[k] / Fs * len(y))
        n[k] = (20 * np.mean(H[1:Ef])) - (20 * np.mean(N[1:Ef]))

    return n
示例#14
0
 def get_influence_matrix(self):
     """
     :return: binary matrix showing influence of input to output
     """
     m = None
     for layer in self.modules():
         if isinstance(layer, nn.Linear):
             if m is None:
                 m = np.find(layer.weight)
             else:
                 m = m* np.find(layer.weight)
     return m
示例#15
0
def pfsoln(baseMVA,
           bus0,
           gen0,
           branch0,
           Ybus,
           Yf,
           Yt,
           V,
           ref,
           ref_gens,
           Ibus=None):
    """Updates bus, gen, branch data structures to match power flow soln.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    # initialize return values
    bus = bus0
    gen = gen0
    branch = branch0

    # ----- update Qg for all gens and Pg for slack bus(es) -----
    # generator info
    on = find(gen[:, GEN_STATUS] > 0)  # which generators are on?
    gbus = gen[on, GEN_BUS].astype(int)  # what buses are they at?

    # xward: add ref buses that are not at the generators
    xbus = setdiff1d(ref, gbus)

    # compute total injected bus powers
    Ibus = zeros(len(V)) if Ibus is None else Ibus
    Sbus = V[gbus] * conj(Ybus[gbus, :] * V - Ibus[gbus])
    Sbus_xw = V[xbus] * conj(Ybus[xbus, :] * V - Ibus[xbus])

    _update_v(bus, V)
    _update_q(baseMVA, bus, gen, gbus, Sbus, on)
    _update_p(baseMVA, bus, gen, ref, gbus, on, r_[Sbus, Sbus_xw], ref_gens)

    # ----- update/compute branch power flows -----
    out = find(branch[:, BR_STATUS] == 0)  # out-of-service branches
    br = find(branch[:, BR_STATUS]).astype(int)  # in-service branches

    if len(out):
        raise RuntimeError
    # complex power at "from" bus
    Sf = V[real(branch[br, F_BUS]).astype(int)] * conj(Yf[br, :] * V) * baseMVA
    # complex power injected at "to" bus
    St = V[real(branch[br, T_BUS]).astype(int)] * conj(Yt[br, :] * V) * baseMVA
    branch[ix_(br, [PF, QF, PT, QT])] = c_[Sf.real, Sf.imag, St.real, St.imag]
    branch[ix_(out, [PF, QF, PT, QT])] = zeros((len(out), 4))

    return bus, gen, branch
示例#16
0
def modcost(gencost, alpha, modtype='SCALE_F'):
    """Modifies generator costs by shifting or scaling (F or X).

    For each generator cost F(X) (for real or reactive power) in
    C{gencost}, this function modifies the cost by scaling or shifting
    the function by C{alpha}, depending on the value of C{modtype}, and
    and returns the modified C{gencost}. Rows of C{gencost} can be a mix
    of polynomial or piecewise linear costs.

    C{modtype} takes one of the 4 possible values (let F_alpha(X) denote the
    the modified function)::
        SCALE_F (default) : F_alpha(X)         == F(X) * ALPHA
        SCALE_X           : F_alpha(X * ALPHA) == F(X)
        SHIFT_F           : F_alpha(X)         == F(X) + ALPHA
        SHIFT_X           : F_alpha(X + ALPHA) == F(X)

    @author: Ray Zimmerman (PSERC Cornell)
    """
    gencost = gencost.copy()

    ng, m = gencost.shape
    if ng != 0:
        ipwl = find(gencost[:, MODEL] == PW_LINEAR)
        ipol = find(gencost[:, MODEL] == POLYNOMIAL)
        c = gencost[ipol, COST:m]

        if modtype == 'SCALE_F':
            gencost[ipol, COST:m] = alpha * c
            gencost[ipwl, COST + 1:m:2] = alpha * gencost[ipwl, COST + 1:m:2]
        elif modtype == 'SCALE_X':
            for k in range(len(ipol)):
                n = gencost[ipol[k], NCOST].astype(int)
                for i in range(n):
                    gencost[ipol[k], COST + i] = c[k, i] / alpha**(n - i - 1)
            gencost[ipwl, COST:m - 1:2] = alpha * gencost[ipwl, COST:m - 1:2]
        elif modtype == 'SHIFT_F':
            for k in range(len(ipol)):
                n = gencost[ipol[k], NCOST].astype(int)
                gencost[ipol[k], COST + n - 1] = alpha + c[k, n - 1]
            gencost[ipwl, COST + 1:m:2] = alpha + gencost[ipwl, COST + 1:m:2]
        elif modtype == 'SHIFT_X':
            for k in range(len(ipol)):
                n = gencost[ipol[k], NCOST].astype(int)
                gencost[ipol[k], COST:COST + n] = \
                        polyshift(c[k, :n].T, alpha).T
            gencost[ipwl, COST:m - 1:2] = alpha + gencost[ipwl, COST:m - 1:2]
        else:
            sys.stderr.write('modcost: "%s" is not a valid modtype\n' %
                             modtype)

    return gencost
示例#17
0
def modcost(gencost, alpha, modtype='SCALE_F'):
    """Modifies generator costs by shifting or scaling (F or X).

    For each generator cost F(X) (for real or reactive power) in
    C{gencost}, this function modifies the cost by scaling or shifting
    the function by C{alpha}, depending on the value of C{modtype}, and
    and returns the modified C{gencost}. Rows of C{gencost} can be a mix
    of polynomial or piecewise linear costs.

    C{modtype} takes one of the 4 possible values (let F_alpha(X) denote the
    the modified function)::
        SCALE_F (default) : F_alpha(X)         == F(X) * ALPHA
        SCALE_X           : F_alpha(X * ALPHA) == F(X)
        SHIFT_F           : F_alpha(X)         == F(X) + ALPHA
        SHIFT_X           : F_alpha(X + ALPHA) == F(X)

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    gencost = gencost.copy()

    ng, m = gencost.shape
    if ng != 0:
        ipwl = find(gencost[:, MODEL] == PW_LINEAR)
        ipol = find(gencost[:, MODEL] == POLYNOMIAL)
        c = gencost[ipol, COST:m]

        if modtype == 'SCALE_F':
            gencost[ipol, COST:m]       = alpha * c
            gencost[ipwl, COST+1:m:2]   = alpha * gencost[ipwl, COST + 1:m:2]
        elif modtype == 'SCALE_X':
            for k in range(len(ipol)):
                n = gencost[ipol[k], NCOST].astype(int)
                for i in range(n):
                    gencost[ipol[k], COST + i] = c[k, i] / alpha**(n - i - 1)
            gencost[ipwl, COST:m - 1:2]   = alpha * gencost[ipwl, COST:m - 1:2]
        elif modtype == 'SHIFT_F':
            for k in range(len(ipol)):
                n = gencost[ipol[k], NCOST].astype(int)
                gencost[ipol[k], COST + n - 1] = alpha + c[k, n - 1]
            gencost[ipwl, COST+1:m:2]   = alpha + gencost[ipwl, COST + 1:m:2]
        elif modtype == 'SHIFT_X':
            for k in range(len(ipol)):
                n = gencost[ipol[k], NCOST].astype(int)
                gencost[ipol[k], COST:COST + n] = \
                        polyshift(c[k, :n].T, alpha).T
            gencost[ipwl, COST:m - 1:2]   = alpha + gencost[ipwl, COST:m - 1:2]
        else:
            sys.stderr.write('modcost: "%s" is not a valid modtype\n' % modtype)

    return gencost
示例#18
0
def getHNR(y, Fs, F0, Nfreqs):
    print 'holla'
    NBins = len(y)
    N0 = round(Fs/F0)
    N0_delta = round(N0 * 0.1)
    
    y = [x*z for x,z in zip(np.hamming(len(y)),y)]
    fftY = np.fft(y, NBins)
    aY = np.log10(abs(fftY))
    ay = np.ifft(aY)
    
    peakinx = np.zeros(np.floor(len(y))/2/N0)
    for k in range(1, len(peakinx)):
        ayseg = ay[k*N0 - N0_delta : k*N0 + N0_delta]
        val, inx = max(abs(ayseg)) #MAX does not behave the same - doesn't return inx??
        peakinx[k] = inx + (k * N0) - N0_delta - 1
        
        s_ayseg = np.sign(np.diff(ayseg))
        
        l_inx = inx - np.find((np.sign(s_ayseg[inx-1:-1:1]) != np.sign(inx)))[0] + 1
        r_inx = inx + np.find(np.sign(s_ayseg[inx+1:]) == np.sign(inx))[0]
        
        l_inx = l_inx + k*N0 - N0_delta - 1
        r_inx = r_inx + k*N0 - N0_delta - 1
        
        for num in range(l_inx, r_inx):
            ay[num] = 0
        
    midL = round(len(y)/2)+1
    ay[midL:] = ay[midL-1: -1 : midL-1-(len(ay)-midL)]
    
    Nap = np.real(np.fft(ay))
    N = Nap #???? why?
    Ha = aY - Nap #change these names ffs
    
    Hdelta = F0/Fs * len(y)
    for f in [num+0.0001 for num in range(Hdelta, round(len(y)/2), Hdelta)]:
        fstart = np.ceil(f - Hdelta)
        Bdf = abs(min(Ha[fstart:round(f)]))
        N[fstart:round(f)] = N[fstart:round(f)] - Bdf
        
    H = aY - N
    n = np.zeros(len(Nfreqs))
    
    for k in range(1, len(Nfreqs)):
        Ef = round(Nfreqs[k] / Fs * len(y))
        n[k] = (20 * np.mean(H[1:Ef])) - (20 * np.mean(N[1:Ef]))
        
    return n
示例#19
0
def makeSbus(baseMVA, bus, gen):
    """Builds the vector of complex bus power injections.

    Returns the vector of complex bus power injections, that is, generation
    minus load. Power is expressed in per unit.

    @see: L{makeYbus}
kk
    @author: Ray Zimmerman (PSERC Cornell)
    """
    ## generator info
    on = find(gen[:, GEN_STATUS] > 0)  ## which generators are on?
    gbus = gen[on, GEN_BUS]  ## what buses are they at?

    ## form net complex bus power injection vector
    nb = bus.shape[0]
    ngon = on.shape[0]
    ## connection matrix, element i, j is 1 if gen on(j) at bus i is ON
    Cg = sparse((ones(ngon), (gbus, range(ngon))), (nb, ngon))

    ## power injected by gens plus power injected by loads converted to p.u.
    Sbus = (Cg * (gen[on, PG] + 1j * gen[on, QG]) -
            (bus[:, PD] + 1j * bus[:, QD])) / baseMVA

    return Sbus
示例#20
0
def makeSbus(baseMVA, bus, gen):
    """Builds the vector of complex bus power injections.

    Returns the vector of complex bus power injections, that is, generation
    minus load. Power is expressed in per unit.

    @see: L{makeYbus}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ## generator info
    on = find(gen[:, GEN_STATUS] > 0)      ## which generators are on?
    gbus = gen[on, GEN_BUS]                   ## what buses are they at?

    ## form net complex bus power injection vector
    nb = bus.shape[0]
    ngon = on.shape[0]
    ## connection matrix, element i, j is 1 if gen on(j) at bus i is ON
    Cg = sparse((ones(ngon), (gbus, range(ngon))), (nb, ngon))

    ## power injected by gens plus power injected by loads converted to p.u.
    Sbus = ( Cg * (gen[on, PG] + 1j * gen[on, QG]) -
             (bus[:, PD] + 1j * bus[:, QD]) ) / baseMVA

    return Sbus
def Theta_abs_mean(dc_bus_sol):
    dc_bus_sol = dc_bus_sol.copy()
    Theta_slack = dc_bus_sol[find(dc_bus_sol[:, 5] == 1)[0], 2]
    dc_bus_sol[:, 2] -= Theta_slack
    dc_ThetaMean = np.mean(abs(dc_bus_sol[:, 2]))

    return dc_ThetaMean
示例#22
0
        def fix_entsoe(dic, limit=10):
            """ Handle DST shift and interpolate remaining nans.
            Error if time starts with last sunday in october 02:00..."""

            time = dic[list(dic)[0]].index
            month, day, wd, hour = time.month, time.day, time.weekday, time.hour
            shift = find((month == 10) & (wd == 6) & (hour == 2) &
                         (day > 24))  # DST shift hours in October
            for i, df in dic.items():
                if i in self.bidz:
                    # DST shift in October
                    for s in shift:
                        if sum(np.isnan(df.iloc[s, :])) > 0 and sum(df.iloc[
                                s - 1, :]) / sum(df.iloc[s - 2, :]) > 1.5:
                            df.iloc[s - 1, :] /= 2
                            df.iloc[s, :] = df.iloc[s - 1, :]

                    # Remaining nans
                    df.interpolate(
                        limit=limit,
                        inplace=True)  # interpolate up to limit samples

                    if np.sum(arr(np.isnan(df))) > 0:
                        print(
                            'Too many nans in Entso-e data for %s, might not work properly.'
                            % i)
            return dic
示例#23
0
def quick_gci(g,
              fmin=20,
              fmax=1000,
              fs=20000,
              theta=0,
              reps=2,
              reps2=None,
              gamma=1,
              inside=False):
    """ Return GCIs using QuickGCI algorithm. """

    Bh, Ah = butter1(fmin / (fs / 2), 'high')
    Bl, Al = butter1(fmax / (fs / 2), 'low')

    for i in range(reps):
        g = sig.filtfilt(Bh, Ah, g)
        g = sig.filtfilt(Bl, Al, g)

    x = fasthilbert(g) * exp(1j * theta)
    q = abs(x)**gamma * imag(-x)

    for i in range(reps if reps2 is None else reps2):
        q = sig.filtfilt(Bl, Al, q)

    r = fasthilbert(q)

    dphi = der(angle(r))
    gci = find(dphi < -1.5 * pi)

    if not inside: return gci
    else: return gci, locals()
示例#24
0
def gadfli(g,
           fmin=20,
           fmax=1000,
           fs=20000,
           m=0.25,
           tau=-0.25,
           theta=0,
           reps=2,
           inside=False):
    """ Return GCIs using GADFLI algorithm. """

    Bh, Ah = butter1(fmin / (fs / 2), 'high')
    Bl, Al = butter1(fmax / (fs / 2), 'low')

    for i in range(reps):
        g = sig.filtfilt(Bh, Ah, g)
        g = sig.filtfilt(Bl, Al, g)

    dg = der(g)
    h = fasthilbert(dg) * exp(1j * theta)

    dphi = der(angle(h))
    gci_c = find(dphi < -1.5 * pi)  # candidates

    rh = real(h)
    kept = inlier_elim(rh, m)
    scale = kept.std()

    gci = array([i for i in gci_c if rh[i] < tau * scale])

    if not inside: return gci
    else: return gci, locals()
示例#25
0
def makeSbus(baseMVA, bus, gen, vm=None):
    """Builds the vector of complex bus power injections.

    Returns the vector of complex bus power injections, that is, generation
    minus load. Power is expressed in per unit.

    @see: L{makeYbus}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ## generator info
    on = find(gen[:, GEN_STATUS] > 0)      ## which generators are on?
    gbus = gen[on, GEN_BUS]                   ## what buses are they at?

    ## form net complex bus power injection vector
    nb = bus.shape[0]
    ngon = on.shape[0]
    ## connection matrix, element i, j is 1 if gen on(j) at bus i is ON
    Cg = sparse((ones(ngon), (gbus, range(ngon))), (nb, ngon))

    S_load = bus[:, PD] + 1j * bus[:, QD]
    if vm is not None:
        ci = bus[:, CID]
        cz = bus[:, CZD]
        cp = (1 - ci - cz)
        volt_depend = cp + ci * vm + cz * vm ** 2
        S_load *= volt_depend
    ## power injected by gens plus power injected by loads converted to p.u.
    Sbus = (Cg * (gen[on, PG] + 1j * gen[on, QG])
            - S_load) / baseMVA

    return Sbus
示例#26
0
def userfcn_iflims_ext2int(ppc, *args):
    """This is the 'ext2int' stage userfcn callback that prepares the input
    data for the formulation stage. It expects to find an 'if' field in
    ppc as described above. The optional args are not currently used.
    """
    ## initialize some things
    ifmap = ppc['if']['map']
    o = ppc['order']
    nl0 = o['ext']['branch'].shape[0]    ## original number of branches
    nl = ppc['branch'].shape[0]          ## number of on-line branches

    ## save if.map for external indexing
    ppc['order']['ext']['ifmap'] = ifmap

    ##-----  convert stuff to internal indexing  -----
    e2i = zeros(nl0)
    e2i[o['branch']['status']['on']] = arange(nl)  ## ext->int branch index mapping
    d = sign(ifmap[:, 1])
    br = abs(ifmap[:, 1]).astype(int)
    ifmap[:, 1] = d * e2i[br]

    ifmap = delete(ifmap, find(ifmap[:, 1] == 0), 0)  ## delete branches that are out

    ppc['if']['map'] = ifmap

    return ppc
示例#27
0
def _update_p(baseMVA, bus, gen, ref, gbus, on, Sbus, ref_gens):
    # update Pg for slack bus(es)
    # inj P + local Pd
    for slack_bus in ref:
        gens_at_bus = find(
            gbus == slack_bus)  # which is(are) the reference gen(s)?
        # xward results come at the PQ buses and not at the PV buses:
        if len(gens_at_bus) == 0:
            bus[slack_bus, PD] = -Sbus[
                slack_bus].real * baseMVA  # negative because it is a PQ bus
            continue
        p_bus = Sbus[gens_at_bus[0]].real * baseMVA + bus[slack_bus, PD]
        if len(gens_at_bus) > 1:  # more than one generator at this ref bus
            # subtract off what is generated by other gens at this bus
            ext_grids = intersect1d(gens_at_bus, ref_gens)
            pv_gens = setdiff1d(gens_at_bus, ext_grids)
            p_ext_grids = p_bus - sum(gen[pv_gens, PG])
            slack_weights = gen[ext_grids, SL_FAC]
            sum_slack_weights = sum(slack_weights)
            if sum_slack_weights > 0:
                # distribute bus slack power according to the distributed slack contribution factors
                gen[ext_grids, PG] = gen[ext_grids, PG] + (p_ext_grids - sum(
                    gen[ext_grids, PG])) * slack_weights / sum_slack_weights
            else:
                gen[ext_grids, PG] = p_ext_grids / len(ext_grids)
        else:
            gen[on[gens_at_bus[0]], PG] = p_bus
示例#28
0
def _update_q(baseMVA, bus, gen, gbus, Sbus, on):
    # update Qg for all generators
    gen[:, QG] = zeros(gen.shape[0])  # zero out all Qg
    gen[on, QG] = Sbus.imag * baseMVA + bus[gbus, QD]  # inj Q + local Qd
    # ... at this point any buses with more than one generator will have
    # the total Q dispatch for the bus assigned to each generator. This
    # must be split between them. We do it first equally, then in proportion
    # to the reactive range of the generator.

    if len(on) > 1:
        # build connection matrix, element i, j is 1 if gen on(i) at bus j is ON
        nb = bus.shape[0]
        ngon = on.shape[0]
        Cg = csr_matrix((ones(ngon), (range(ngon), gbus)), (ngon, nb))

        # divide Qg by number of generators at the bus to distribute equally
        ngg = Cg * Cg.sum(0).T  # ngon x 1, number of gens at this gen's bus
        ngg = asarray(ngg).flatten()  # 1D array
        gen[on, QG] = gen[on, QG] / ngg

        # divide proportionally
        Cmin = csr_matrix((gen[on, QMIN], (range(ngon), gbus)), (ngon, nb))
        Cmax = csr_matrix((gen[on, QMAX], (range(ngon), gbus)), (ngon, nb))
        Qg_tot = Cg.T * gen[on, QG]  # nb x 1 vector of total Qg at each bus
        Qg_min = Cmin.sum(0).T  # nb x 1 vector of min total Qg at each bus
        Qg_max = Cmax.sum(0).T  # nb x 1 vector of max total Qg at each bus
        Qg_min = asarray(Qg_min).flatten()  # 1D array
        Qg_max = asarray(Qg_max).flatten()  # 1D array
        # gens at buses with Qg range = 0
        ig = find(Cg * Qg_min == Cg * Qg_max)
        Qg_save = gen[on[ig], QG]
        gen[on, QG] = gen[on, QMIN] + (Cg * ((Qg_tot - Qg_min) / (Qg_max - Qg_min + EPS))) * \
                      (gen[on, QMAX] - gen[on, QMIN])  # ^ avoid div by 0
        gen[on[ig], QG] = Qg_save  # (terms are mult by 0 anyway)
示例#29
0
def pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref, ref_gens, Ibus=None):
    """Updates bus, gen, branch data structures to match power flow soln.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    # generator info
    on = find(gen[:, GEN_STATUS] > 0)  # which generators are on?
    gbus = gen[on, GEN_BUS].astype(int)  # what buses are they at?

    # xward: add ref buses that are not at the generators
    xbus = setdiff1d(ref, gbus)

    # compute total injected bus powers
    Ibus = zeros(len(V)) if Ibus is None else Ibus
    Sbus = V[gbus] * conj(Ybus[gbus, :] * V - Ibus[gbus])
    Sbus_xw = V[xbus] * conj(Ybus[xbus, :] * V - Ibus[xbus])

    _update_v(bus, V)
    # update gen results
    _update_q(baseMVA, bus, gen, gbus, Sbus, on)
    _update_p(baseMVA, bus, gen, ref, gbus, on, r_[Sbus, Sbus_xw], ref_gens)

    # ----- update/compute branch power flows -----
    branch = _update_branch_flows(Yf, Yt, V, baseMVA, branch)

    return bus, gen, branch
示例#30
0
    def line_walk(self, p):
        NC = self.number_of_cells()
        NP = p.shape[0]
        cell = self.entity('cell')

        cidx = np.random.randint(0, NC, NP)
        isNotOK = np.ones(NP, dtype=np.bool)
        while isNotOK.sum() > 0:
            idx0, = np.find(isNotOK)
            cidx0 = cidx[isNotOK]
            pp = p[isNotOK]

            a = np.zeros((len(cidx0), 3), dtype=self.ftype)
            p0 = cell[cidx0, 0]
            p1 = cell[cidx0, 1]
            p2 = cell[cidx0, 2]

            v0 = p0 - pp
            v1 = p1 - pp
            v2 = p2 - pp
            a[:, 0] = np.cross(v1, v2)
            a[:, 1] = np.cross(v2, v0)
            a[:, 2] = np.cross(v0, v1)
            idx = np.argmin(a, axis=-1)

            isOK = a[range(a.shape[0]), idx] >= 0
示例#31
0
def userfcn_iflims_ext2int(ppc, *args):
    """This is the 'ext2int' stage userfcn callback that prepares the input
    data for the formulation stage. It expects to find an 'if' field in
    ppc as described above. The optional args are not currently used.
    """
    ## initialize some things
    ifmap = ppc['if']['map']
    o = ppc['order']
    nl0 = o['ext']['branch'].shape[0]  ## original number of branches
    nl = ppc['branch'].shape[0]  ## number of on-line branches

    ## save if.map for external indexing
    ppc['order']['ext']['ifmap'] = ifmap

    ##-----  convert stuff to internal indexing  -----
    e2i = zeros(nl0)
    e2i[o['branch']['status']['on']] = arange(
        nl)  ## ext->int branch index mapping
    d = sign(ifmap[:, 1])
    br = abs(ifmap[:, 1]).astype(int)
    ifmap[:, 1] = d * e2i[br]

    ifmap = delete(ifmap, find(ifmap[:, 1] == 0),
                   0)  ## delete branches that are out

    ppc['if']['map'] = ifmap

    return ppc
示例#32
0
def optimal_power_flow_energy_reserve(*args):
    casedata = args[0] # Target power flow modelling
    beta = args[1] # The reserve level
    mpc = loadcase(casedata) # Import the power flow modelling
    ## convert to internal indexing
    mpc = ext2int(mpc)
    baseMVA, bus, gen, branch,gencost = mpc["baseMVA"], mpc["bus"], mpc["gen"], mpc["branch"],mpc["gencost"] #

    nb = shape(mpc['bus'])[0]  ## number of buses
    nl = shape(mpc['branch'])[0]  ## number of branches
    ng = shape(mpc['gen'])[0]  ## number of dispatchable injections

    ## Formualte the
    stat = branch[:, BR_STATUS]  ## ones at in-service branches
    b = stat / branch[:, BR_X]  ## series susceptance
    tap = ones(nl)  ## default tap ratio = 1
    i = find(branch[:, TAP])  ## indices of non-zero tap ratios
    tap[i] = branch[i, TAP]  ## assign non-zero tap ratios

    ## build connection matrix Cft = Cf - Ct for line and from - to buses
    f = branch[:, F_BUS]  ## list of "from" buses
    t = branch[:, T_BUS]  ## list of "to" buses
    i = r_[range(nl), range(nl)]  ## double set of row indices
    ## connection matrix
    Cft = sparse((r_[ones(nl), -ones(nl)], (i, r_[f, t])), (nl, nb))

    ## build Bf such that Bf * Va is the vector of real branch powers injected
    ## at each branch's "from" bus
    Bf = sparse((r_[b, -b], (i, r_[f, t])), shape=(nl, nb))  ## = spdiags(b, 0, nl, nl) * Cft

    ## build Bbus
    Bbus = Cft.T * Bf
    # The distribution factor
    Distribution_factor = sparse(Bf*inv(Bbus))

    Cg = sparse((ones(ng), (gen[:, GEN_BUS], arange(ng))), (nb, ng)) # Sparse index generation method is different from the way of matlab
    Cd = sparse((ones(nb), (bus[:, BUS_I], arange(nb))), (nb, nb)) # Sparse index load

    Pd = sum(bus[:,PD]) # Total power demand

    # Formulate the problem
    lb = concatenate((gen[:,PMIN],zeros(ng))) # extend the
    ub = concatenate((gen[:,PMAX],gen[:,PMAX]))
    Aeq = sparse(concatenate((ones(ng),zeros(ng))))
    beq = [Pd]

    Aineq = sparse(hstack([Distribution_factor * Cg,zeros((nl,ng))]))
    Aineq = vstack([Aineq, -Aineq])
    # The ramp reserve requirement
    Aineq = vstack([Aineq, sparse((r_[ones(ng), ones(ng)], (r_[arange(ng), arange(ng)], r_[arange(ng), ng+arange(ng)])), (ng, 2*ng))])
    Aineq = vstack([Aineq, sparse((r_[-ones(ng), ones(ng)], (r_[arange(ng), arange(ng)], r_[arange(ng), ng+arange(ng)])), (ng, 2*ng))])
    bineq = concatenate((branch[:, RATE_A] + Distribution_factor * Cd * bus[:, PD], branch[:, RATE_A] - Distribution_factor * Cd * bus[:, PD]))
    bineq = concatenate((bineq, gen[:, PMAX]))
    bineq = concatenate((bineq, -gen[:, PMIN]))
    c = concatenate((gencost[:,5],zeros(ng)))
    Q = diag(concatenate((gencost[:,4],zeros(ng))))
    (Pg,obj) = miqp_gurobi(c = c,Q = Q, Aeq = Aeq, beq = beq, A = Aineq, b = bineq, xmin = lb,xmax = ub)
    obj =  obj + sum(gencost[:,6])
    return Pg, obj
示例#33
0
def makeAang(baseMVA, branch, nb, ppopt):
    """Construct constraints for branch angle difference limits.

    Constructs the parameters for the following linear constraint limiting
    the voltage angle differences across branches, where C{Va} is the vector
    of bus voltage angles. C{nb} is the number of buses::

        lang <= Aang * Va <= uang

    C{iang} is the vector of indices of branches with angle difference limits.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    ## options
    ignore_ang_lim = ppopt['OPF_IGNORE_ANG_LIM']

    if ignore_ang_lim:
        Aang  = zeros((0, nb))
        lang  = array([])
        uang  = array([])
        iang  = array([])
    else:
        iang = find(((branch[:, ANGMIN] != 0) & (branch[:, ANGMIN] > -360)) |
                    ((branch[:, ANGMAX] != 0) & (branch[:, ANGMAX] <  360)))
        iangl = find(branch[iang, ANGMIN])
        iangh = find(branch[iang, ANGMAX])
        nang = len(iang)

        if nang > 0:
            ii = r_[arange(nang), arange(nang)]
            jj = r_[branch[iang, F_BUS], branch[iang, T_BUS]]
            Aang = sparse((r_[ones(nang), -ones(nang)],
                           (ii, jj)), (nang, nb))
            uang = Inf * ones(nang)
            lang = -uang
            lang[iangl] = branch[iang[iangl], ANGMIN] * pi / 180
            uang[iangh] = branch[iang[iangh], ANGMAX] * pi / 180
        else:
            Aang  = zeros((0, nb))
            lang  = array([])
            uang  = array([])

    return Aang, lang, uang, iang
def makeAang(baseMVA, branch, nb, ppopt):
    """Construct constraints for branch angle difference limits.

    Constructs the parameters for the following linear constraint limiting
    the voltage angle differences across branches, where C{Va} is the vector
    of bus voltage angles. C{nb} is the number of buses::

        lang <= Aang * Va <= uang

    C{iang} is the vector of indices of branches with angle difference limits.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    ## options
    ignore_ang_lim = ppopt['OPF_IGNORE_ANG_LIM']

    if ignore_ang_lim:
        Aang  = zeros((0, nb))
        lang  = array([])
        uang  = array([])
        iang  = array([])
    else:
        iang = find(((branch[:, ANGMIN] != 0) & (branch[:, ANGMIN] > -360)) |
                    ((branch[:, ANGMAX] != 0) & (branch[:, ANGMAX] <  360)))
        iangl = find(branch[iang, ANGMIN])
        iangh = find(branch[iang, ANGMAX])
        nang = len(iang)

        if nang > 0:
            ii = r_[arange(nang), arange(nang)]
            jj = r_[branch[iang, F_BUS], branch[iang, T_BUS]]
            Aang = sparse((r_[ones(nang), -ones(nang)],
                           (ii, jj)), (nang, nb))
            uang = Inf * ones(nang)
            lang = -uang
            lang[iangl] = branch[iang[iangl], ANGMIN] * pi / 180
            uang[iangh] = branch[iang[iangh], ANGMAX] * pi / 180
        else:
            Aang  = zeros((0, nb))
            lang  = array([])
            uang  = array([])

    return Aang, lang, uang, iang
示例#35
0
def userfcn_reserves_formulation(om, *args):
    """This is the 'formulation' stage userfcn callback that defines the
    user costs and constraints for fixed reserves. It expects to find
    a 'reserves' field in the ppc stored in om, as described above.
    By the time it is passed to this callback, ppc['reserves'] should
    have two additional fields:
        - C{igr}     C{1 x ngr}, indices of generators available for reserves
        - C{rgens}   C{1 x ng}, 1 if gen avaiable for reserves, 0 otherwise
    It is also assumed that if cost or qty were C{ngr x 1}, they have been
    expanded to C{ng x 1} and that everything has been converted to
    internal indexing, i.e. all gens are on-line (by the 'ext2int'
    callback). The optional args are not currently used.
    """
    ## initialize some things
    ppc = om.get_ppc()
    r = ppc['reserves']
    igr = r['igr']  ## indices of gens available to provide reserves
    ngr = len(igr)  ## number of gens available to provide reserves
    ng = ppc['gen'].shape[0]  ## number of on-line gens (+ disp loads)

    ## variable bounds
    Rmin = zeros(ngr)  ## bound below by 0
    Rmax = Inf * ones(ngr)  ## bound above by ...
    k = find(ppc['gen'][igr, RAMP_10])
    Rmax[k] = ppc['gen'][igr[k], RAMP_10]  ## ... ramp rate and ...
    if 'qty' in r:
        k = find(r['qty'][igr] < Rmax)
        Rmax[k] = r['qty'][igr[k]]  ## ... stated max reserve qty
    Rmax = Rmax / ppc['baseMVA']

    ## constraints
    I = speye(ngr, ngr, format='csr')  ## identity matrix
    Ar = hstack([sparse((ones(ngr), (arange(ngr), igr)), (ngr, ng)), I], 'csr')
    ur = ppc['gen'][igr, PMAX] / ppc['baseMVA']
    lreq = r['req'] / ppc['baseMVA']

    ## cost
    Cw = r['cost'][igr] * ppc['baseMVA']  ## per unit cost coefficients

    ## add them to the model
    om.add_vars('R', ngr, [], Rmin, Rmax)
    om.add_constraints('Pg_plus_R', Ar, [], ur, ['Pg', 'R'])
    om.add_constraints('Rreq', sparse(r['zones'][:, igr]), lreq, [], ['R'])
    om.add_costs('Rcost', {'N': I, 'Cw': Cw}, ['R'])

    return om
示例#36
0
def userfcn_reserves_formulation(om, *args):
    """This is the 'formulation' stage userfcn callback that defines the
    user costs and constraints for fixed reserves. It expects to find
    a 'reserves' field in the ppc stored in om, as described above.
    By the time it is passed to this callback, ppc['reserves'] should
    have two additional fields:
        - C{igr}     C{1 x ngr}, indices of generators available for reserves
        - C{rgens}   C{1 x ng}, 1 if gen avaiable for reserves, 0 otherwise
    It is also assumed that if cost or qty were C{ngr x 1}, they have been
    expanded to C{ng x 1} and that everything has been converted to
    internal indexing, i.e. all gens are on-line (by the 'ext2int'
    callback). The optional args are not currently used.
    """
    ## initialize some things
    ppc = om.get_ppc()
    r = ppc['reserves']
    igr = r['igr']                ## indices of gens available to provide reserves
    ngr = len(igr)                ## number of gens available to provide reserves
    ng  = ppc['gen'].shape[0]     ## number of on-line gens (+ disp loads)

    ## variable bounds
    Rmin = zeros(ngr)               ## bound below by 0
    Rmax = Inf * ones(ngr)          ## bound above by ...
    k = find(ppc['gen'][igr, RAMP_10])
    Rmax[k] = ppc['gen'][igr[k], RAMP_10] ## ... ramp rate and ...
    if 'qty' in r:
        k = find(r['qty'][igr] < Rmax)
        Rmax[k] = r['qty'][igr[k]]        ## ... stated max reserve qty
    Rmax = Rmax / ppc['baseMVA']

    ## constraints
    I = speye(ngr, ngr, format='csr')                     ## identity matrix
    Ar = hstack([sparse((ones(ngr), (arange(ngr), igr)), (ngr, ng)), I], 'csr')
    ur = ppc['gen'][igr, PMAX] / ppc['baseMVA']
    lreq = r['req'] / ppc['baseMVA']

    ## cost
    Cw = r['cost'][igr] * ppc['baseMVA']     ## per unit cost coefficients

    ## add them to the model
    om.add_vars('R', ngr, [], Rmin, Rmax)
    om.add_constraints('Pg_plus_R', Ar, [], ur, ['Pg', 'R'])
    om.add_constraints('Rreq', sparse( r['zones'][:, igr] ), lreq, [], ['R'])
    om.add_costs('Rcost', {'N': I, 'Cw': Cw}, ['R'])

    return om
示例#37
0
def userfcn_dcline_int2ext(results, args):
    """This is the 'int2ext' stage userfcn callback that converts everything
    back to external indexing and packages up the results. It expects to
    find a 'dcline' field in the results struct as described for ppc
    above. It also expects that the last 2*ndc entries in the gen and
    gencost matrices correspond to the in-service DC lines (where ndc is
    the number of rows in MPC.dcline. These extra rows are removed from
    gen and gencost and the flow is taken from the PG of these gens and
    placed in the flow column of the appropiate dcline row. The
    optional args are not currently used.
    """
    c = idx_dcline.c

    ## initialize some things
    o = results['order']
    k = find(o['ext']['dcline'][:, c['BR_STATUS']])
    ndc = len(k)                    ## number of in-service DC lines
    ng  = results['gen'].shape[0] - 2*ndc; ## number of original gens/disp loads

    ## extract dummy gens
    fg = results['gen'][ng:ng + ndc, :]
    tg = results['gen'][ng + ndc:ng + 2 * ndc, :]

    ## remove dummy gens
    #results['gen']     = results['gen'][:ng + 1, :]
    #results['gencost'] = results['gencost'][:ng + 1, :]
    results['gen']     = results['gen'][:ng, :]
    results['gencost'] = results['gencost'][:ng, :]

    ## get the solved flows
    results['dcline'][:, c['PF']] = -fg[:, PG]
    results['dcline'][:, c['PT']] =  tg[:, PG]
    results['dcline'][:, c['QF']] =  fg[:, QG]
    results['dcline'][:, c['QT']] =  tg[:, QG]
    results['dcline'][:, c['VF']] =  fg[:, VG]
    results['dcline'][:, c['VT']] =  tg[:, VG]
    if fg.shape[1] >= MU_QMIN:
        results['dcline'] = c_[results['dcline'], zeros((ndc, 6))]
        results['dcline'][:, c['MU_PMIN'] ] = fg[:, MU_PMAX] + tg[:, MU_PMIN]
        results['dcline'][:, c['MU_PMAX'] ] = fg[:, MU_PMIN] + tg[:, MU_PMAX]
        results['dcline'][:, c['MU_QMINF']] = fg[:, MU_QMIN]
        results['dcline'][:, c['MU_QMAXF']] = fg[:, MU_QMAX]
        results['dcline'][:, c['MU_QMINT']] = tg[:, MU_QMIN]
        results['dcline'][:, c['MU_QMAXT']] = tg[:, MU_QMAX]

    results['order']['int'] = {}
    ##-----  convert stuff back to external indexing  -----
    results['order']['int']['dcline'] = results['dcline']  ## save internal version
    ## copy results to external version
    o['ext']['dcline'][k, c['PF']:c['VT'] + 1] = results['dcline'][:, c['PF']:c['VT'] + 1]
    if results['dcline'].shape[1] == c['MU_QMAXT'] + 1:
        o['ext']['dcline'] = c_[o['ext']['dcline'], zeros((ndc, 6))]
        o['ext']['dcline'][k, c['MU_PMIN']:c['MU_QMAXT'] + 1] = \
                results['dcline'][:, c['MU_PMIN']:c['MU_QMAXT'] + 1]

    results['dcline'] = o['ext']['dcline']            ## use external version

    return results
示例#38
0
def inlier_elim(b, m):
    """ Apply inlier elimination, return remaining samples. """
    while True:
        s = b.std()
        idx = find(abs(b) >= m * s)
        if len(idx) != len(b):
            b = b[idx]
        else:
            return b
示例#39
0
def findTieline(bus, branch):
    tl = find(bus[branch[:, F_BUS].astype(int), BUS_AREA] != \
     bus[branch[:, T_BUS].astype(int), BUS_AREA])
    ntl = len(tl)
    busBD = branch[ix_(tl, [F_BUS, T_BUS])].astype(int)
    busBDregion = hstack((bus[ix_(busBD[:, 0], [BUS_AREA])], \
     bus[ix_(busBD[:, 1], [BUS_AREA])])).astype(int)
    tieline = hstack((busBD, busBDregion, tl.reshape((ntl, 1))))
    return tieline, ntl
示例#40
0
def userfcn_dcline_int2ext(results, args):
    """This is the 'int2ext' stage userfcn callback that converts everything
    back to external indexing and packages up the results. It expects to
    find a 'dcline' field in the results struct as described for ppc
    above. It also expects that the last 2*ndc entries in the gen and
    gencost matrices correspond to the in-service DC lines (where ndc is
    the number of rows in MPC.dcline. These extra rows are removed from
    gen and gencost and the flow is taken from the PG of these gens and
    placed in the flow column of the appropiate dcline row. The
    optional args are not currently used.
    """
    c = idx_dcline.c

    ## initialize some things
    o = results['order']
    k = find(o['ext']['dcline'][:, c.BR_STATUS])
    ndc = len(k)  ## number of in-service DC lines
    ng = results['gen'].shape[0] - 2 * ndc
    ## number of original gens/disp loads

    ## extract dummy gens
    fg = results['gen'][ng + range(ndc + 1), :]
    tg = results['gen'][ng + ndc + range(ndc + 1), :]

    ## remove dummy gens
    results['gen'] = results['gen'][:ng + 1, :]
    results['gencost'] = results['gencost'][:ng + 1, :]

    ## get the solved flows
    results['dcline'][:, c.PF] = -fg[:, PG]
    results['dcline'][:, c.PT] = tg[:, PG]
    results['dcline'][:, c.QF] = fg[:, QG]
    results['dcline'][:, c.QT] = tg[:, QG]
    results['dcline'][:, c.VF] = fg[:, VG]
    results['dcline'][:, c.VT] = tg[:, VG]
    if fg.shape[1] >= MU_QMIN:
        results['dcline'][:, c.MU_PMIN] = fg[:, MU_PMAX] + tg[:, MU_PMIN]
        results['dcline'][:, c.MU_PMAX] = fg[:, MU_PMIN] + tg[:, MU_PMAX]
        results['dcline'][:, c.MU_QMINF] = fg[:, MU_QMIN]
        results['dcline'][:, c.MU_QMAXF] = fg[:, MU_QMAX]
        results['dcline'][:, c.MU_QMINT] = tg[:, MU_QMIN]
        results['dcline'][:, c.MU_QMAXT] = tg[:, MU_QMAX]

    ##-----  convert stuff back to external indexing  -----
    results['order']['int']['dcline'] = results[
        'dcline']  ## save internal version
    ## copy results to external version
    o['ext']['dcline'][k, c.PF:c.VT + 1] = results['dcline'][:, c.PF:c.VT + 1]
    if results['dcline'].shape[1] == c.MU_QMAXT:
        o['ext']['dcline'][k, c.MU_PMIN:c.MU_QMAXT + 1] = \
                results['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1]

    results['dcline'] = o['ext']['dcline']  ## use external version

    return results
    def plot_settings(self):
        """ Plotting settings (colors, linewidths etc.), possibly depending on bus variable.
        """

        var = 'Vbase'  # base colors etc on Vbase
        var_lim = [380, 300,
                   0]  # different categories of Vbase, should be a list

        # bus settings
        self.sets_variable_lim = var_lim
        var = self.bus.loc[:, var]
        self.bus_set = arr([
            find(v >= arr(var_lim))[0] if v >= var_lim[-1] else -1 for v in var
        ])
        self.bus_color = ['r', (230. / 255, 152. / 255, 0), 'g']
        self.bus_name_color = ['k'] * 3
        self.bus_lw = [1.5, 1, 1]
        self.bus_name_fs = [0, 0, 0]

        # line settings
        var_line = var.loc[self.line.bus0]
        self.line_set = arr([
            find(v >= arr(var_lim))[0] if v >= var_lim[-1] else -1
            for v in var_line
        ])
        self.line_lw = [1, 1, 1]
        self.line_color = ['r', (230. / 255, 152. / 255, 0), 'g']

        # Link
        self.link_lw = 1
        self.link_color = 'b'

        # Interactive plot
        self.interactive = True  # interactive map mode
        self.picker_node = 7  # tolerance for interactive picking
        self.picker_arc = 3
        self.significant_figures = 3  # when info is displayed
        self.info_fc = [213. / 255, 230. / 255, 1]  # color for info box
        self.info_ec = 'k'  # color info-box edge
        self.info_lw = 1  # info-box edge width

        self.equal_aspect = False
示例#42
0
def bustypes(bus, gen):
    """Builds index lists of each type of bus (C{REF}, C{PV}, C{PQ}).

    Generators with "out-of-service" status are treated as L{PQ} buses with
    zero generation (regardless of C{Pg}/C{Qg} values in gen). Expects C{bus}
    and C{gen} have been converted to use internal consecutive bus numbering.

    @param bus: bus data
    @param gen: generator data
    @return: index lists of each bus type

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln

    changes by Uni Kassel (Florian Schaefer): If new ref bus is chosen -> Init as numpy array
    """
    # get generator status
    nb = bus.shape[0]
    ng = gen.shape[0]
    # gen connection matrix, element i, j is 1 if, generator j at bus i is ON
    Cg = sparse((gen[:, GEN_STATUS] > 0, (gen[:, GEN_BUS], range(ng))),
                (nb, ng))
    # number of generators at each bus that are ON
    bus_gen_status = (Cg * ones(ng, int)).astype(bool)

    # form index lists for slack, PV, and PQ buses
    ref = find((bus[:, BUS_TYPE] == REF) & bus_gen_status)  # ref bus index
    pv = find((bus[:, BUS_TYPE] == PV) & bus_gen_status)  # PV bus indices
    pq = find((bus[:, BUS_TYPE] == PQ) | ~bus_gen_status)  # PQ bus indices

    # throw an error since no reference bus is defined
    if len(ref) == 0:
        raise KeyError(
            "No reference bus (ext_grid) is available. Abort power flow calculation. Please add an ext_grid"
        )
        # bugfix Pypower: must be an numpy array!
        # ref = zeros(1, dtype=int)
        # ref[0] = pv[0]      # use the first PV bus
        # pv = pv[1:]      # take it off PV list

    return ref, pv, pq
示例#43
0
def totcost(gencost, Pg):
    """Computes total cost for generators at given output level.

    Computes total cost for generators given a matrix in gencost format and
    a column vector or matrix of generation levels. The return value has the
    same dimensions as PG. Each row of C{gencost} is used to evaluate the
    cost at the points specified in the corresponding row of C{Pg}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    ng, m = gencost.shape
    totalcost = zeros(ng)

    if len(gencost) > 0:
        ipwl = find(gencost[:, MODEL] == PW_LINEAR)
        ipol = find(gencost[:, MODEL] == POLYNOMIAL)
        if len(ipwl) > 0:
            p = gencost[:, COST:(m-1):2]
            c = gencost[:, (COST+1):m:2]

            for i in ipwl:
                ncost = gencost[i, NCOST]
                for k in arange(ncost - 1):
                    p1, p2 = p[i, k], p[i, k+1]
                    c1, c2 = c[i, k], c[i, k+1]
                    m = (c2 - c1) / (p2 - p1)
                    b = c1 - m * p1
                    Pgen = Pg[i]
                    if Pgen < p2:
                        totalcost[i] = m * Pgen + b
                        break
                    totalcost[i] = m * Pgen + b

        if len(ipol) > 0:
            totalcost[ipol] = polycost(gencost[ipol, :], Pg[ipol])

    return totalcost
def totcost(gencost, Pg):
    """Computes total cost for generators at given output level.

    Computes total cost for generators given a matrix in gencost format and
    a column vector or matrix of generation levels. The return value has the
    same dimensions as PG. Each row of C{gencost} is used to evaluate the
    cost at the points specified in the corresponding row of C{Pg}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    ng, m = gencost.shape
    totalcost = zeros(ng)

    if len(gencost) > 0:
        ipwl = find(gencost[:, MODEL] == PW_LINEAR)
        ipol = find(gencost[:, MODEL] == POLYNOMIAL)
        if len(ipwl) > 0:
            p = gencost[:, COST:(m-1):2]
            c = gencost[:, (COST+1):m:2]

            for i in ipwl:
                ncost = gencost[i, NCOST]
                for k in arange(ncost - 1):
                    p1, p2 = p[i, k], p[i, k+1]
                    c1, c2 = c[i, k], c[i, k+1]
                    m = (c2 - c1) / (p2 - p1)
                    b = c1 - m * p1
                    Pgen = Pg[i]
                    if Pgen < p2:
                        totalcost[i] = m * Pgen + b
                        break
                    totalcost[i] = m * Pgen + b

        if len(ipol) > 0:
            totalcost[ipol] = polycost(gencost[ipol, :], Pg[ipol])

    return totalcost
示例#45
0
def polycost(gencost, Pg, der=0):
    """Evaluates polynomial generator cost & derivatives.

    C{f = polycost(gencost, Pg)} returns the vector of costs evaluated at C{Pg}

    C{df = polycost(gencost, Pg, 1)} returns the vector of first derivatives
    of costs evaluated at C{Pg}

    C{d2f = polycost(gencost, Pg, 2)} returns the vector of second derivatives
    of costs evaluated at C{Pg}

    C{gencost} must contain only polynomial costs
    C{Pg} is in MW, not p.u. (works for C{Qg} too)

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    if any(gencost[:, MODEL] == PW_LINEAR):
        sys.stderr.write('polycost: all costs must be polynomial\n')

    ng = len(Pg)
    maxN = max( gencost[:, NCOST].astype(int) )
    minN = min( gencost[:, NCOST].astype(int) )

    ## form coefficient matrix where 1st column is constant term, 2nd linear, etc.
    c = zeros((ng, maxN))
    for n in arange(minN, maxN + 1):
        k = find(gencost[:, NCOST] == n)   ## cost with n coefficients
        c[k, :n] = gencost[k, (COST + n - 1):COST - 1:-1]

    ## do derivatives
    for d in range(1, der + 1):
        if c.shape[1] >= 2:
            c = c[:, 1:maxN - d + 1]
        else:
            c = zeros((ng, 1))
            break

        for k in range(2, maxN - d + 1):
            c[:, k-1] = c[:, k-1] * k

    ## evaluate polynomial
    if len(c) == 0:
        f = zeros(Pg.shape)
    else:
        f = c[:, :1].flatten()  ## constant term
        for k in range(1, c.shape[1]):
            f = f + c[:, k] * Pg**k

    return f
def despike(datax,datay,threshold=3.0,interpolate=False):
    """
    Remove spikes larger than threshold*(standard deviation of diffs in datay).
    interpolate=False (default) just removes the points;
    interpolate=True will just make them equal to the point to the left 
    (if you need to keep array length constant, say).
    """
    d = np.diff(datay)
    spikes = np.find(abs(d)>threshold*std(d)) 
    if (len(spikes)>0.1*len(d)): 
        print 'Did not remove spikes because it wanted to remove too many.'
        return datax,datay # if we're trying to remove a lot of points, just send it back...
    spikes=np.delete(spikes,find(diff(spikes)==1)+1) # if spike is one point, don't delete point after as well.
    if interpolate==False:
        datax = np.delete(datax,spikes+1)
        datay = np.delete(datay,spikes+1)
    else:
        # don't actually 'interpolate', just set it equal to the previous point
        # (actual interpolation could get messy in the case of a two-point spike, for example)
        for i in spikes+1: datay[i] = datay[i-3]
    if (np.any(np.abs(diff(datay))>threshold*np.std(d))): datax,datay = despike(datax,datay,threshold,interpolate)
    return datax, datay
示例#47
0
def pipsopf_solver(om, ppopt, out_opt=None):
    """Solves AC optimal power flow using PIPS.

    Inputs are an OPF model object, a PYPOWER options vector and
    a dict containing keys (can be empty) for each of the desired
    optional output fields.

    outputs are a C{results} dict, C{success} flag and C{raw} output dict.

    C{results} is a PYPOWER case dict (ppc) with the usual baseMVA, bus
    branch, gen, gencost fields, along with the following additional
    fields:
        - C{order}      see 'help ext2int' for details of this field
        - C{x}          final value of optimization variables (internal order)
        - C{f}          final objective function value
        - C{mu}         shadow prices on ...
            - C{var}
                - C{l}  lower bounds on variables
                - C{u}  upper bounds on variables
            - C{nln}
                - C{l}  lower bounds on nonlinear constraints
                - C{u}  upper bounds on nonlinear constraints
            - C{lin}
                - C{l}  lower bounds on linear constraints
                - C{u}  upper bounds on linear constraints

    C{success} is C{True} if solver converged successfully, C{False} otherwise

    C{raw} is a raw output dict in form returned by MINOS
        - xr     final value of optimization variables
        - pimul  constraint multipliers
        - info   solver specific termination code
        - output solver specific output information

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

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    ##----- initialization -----
    ## optional output
    if out_opt is None:
        out_opt = {}

    ## options
    verbose = ppopt['VERBOSE']
    feastol = ppopt['PDIPM_FEASTOL']
    gradtol = ppopt['PDIPM_GRADTOL']
    comptol = ppopt['PDIPM_COMPTOL']
    costtol = ppopt['PDIPM_COSTTOL']
    max_it  = ppopt['PDIPM_MAX_IT']
    max_red = ppopt['SCPDIPM_RED_IT']
    step_control = (ppopt['OPF_ALG'] == 565)  ## OPF_ALG == 565, PIPS-sc
    if feastol == 0:
        feastol = ppopt['OPF_VIOLATION']
    opt = {  'feastol': feastol,
             'gradtol': gradtol,
             'comptol': comptol,
             'costtol': costtol,
             'max_it': max_it,
             'max_red': max_red,
             'step_control': step_control,
             'cost_mult': 1e-4,
             'verbose': verbose  }

    ## unpack data
    ppc = om.get_ppc()
    baseMVA, bus, gen, branch, gencost = \
        ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
    vv, _, nn, _ = om.get_idx()

    ## problem dimensions
    nb = bus.shape[0]          ## number of buses
    nl = branch.shape[0]       ## number of branches
    ny = om.getN('var', 'y')   ## number of piece-wise linear costs

    ## linear constraints
    A, l, u = om.linear_constraints()

    ## bounds on optimization vars
    _, xmin, xmax = om.getv()

    ## build admittance matrices
    Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)

    ## try to select an interior initial point
    ll, uu = xmin.copy(), xmax.copy()
    ll[xmin == -Inf] = -1e10   ## replace Inf with numerical proxies
    uu[xmax ==  Inf] =  1e10
    x0 = (ll + uu) / 2
    Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180)
    ## angles set to first reference angle
    x0[vv["i1"]["Va"]:vv["iN"]["Va"]] = Varefs[0]
    if ny > 0:
        ipwl = find(gencost[:, MODEL] == PW_LINEAR)
#         PQ = r_[gen[:, PMAX], gen[:, QMAX]]
#         c = totcost(gencost[ipwl, :], PQ[ipwl])
        c = gencost.flatten('F')[sub2ind(gencost.shape, ipwl, NCOST+2*gencost[ipwl, NCOST])]    ## largest y-value in CCV data
        x0[vv["i1"]["y"]:vv["iN"]["y"]] = max(c) + 0.1 * abs(max(c))
#        x0[vv["i1"]["y"]:vv["iN"]["y"]] = c + 0.1 * abs(c)

    ## find branches with flow limits
    il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
    nl2 = len(il)           ## number of constrained lines

    ##-----  run opf  -----
    f_fcn = lambda x, return_hessian=False: opf_costfcn(x, om, return_hessian)
    gh_fcn = lambda x: opf_consfcn(x, om, Ybus, Yf[il, :], Yt[il,:], ppopt, il)
    hess_fcn = lambda x, lmbda, cost_mult: opf_hessfcn(x, lmbda, om, Ybus, Yf[il, :], Yt[il, :], ppopt, il, cost_mult)

    solution = pips(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt)
    x, f, info, lmbda, output = solution["x"], solution["f"], \
            solution["eflag"], solution["lmbda"], solution["output"]

    success = (info > 0)

    ## update solution data
    Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
    Vm = x[vv["i1"]["Vm"]:vv["iN"]["Vm"]]
    Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]]
    Qg = x[vv["i1"]["Qg"]:vv["iN"]["Qg"]]

    V = Vm * exp(1j * Va)

    ##-----  calculate return values  -----
    ## update voltages & generator outputs
    bus[:, VA] = Va * 180 / pi
    bus[:, VM] = Vm
    gen[:, PG] = Pg * baseMVA
    gen[:, QG] = Qg * baseMVA
    gen[:, VG] = Vm[ gen[:, GEN_BUS].astype(int) ]

    ## compute branch flows
    Sf = V[ branch[:, F_BUS].astype(int) ] * conj(Yf * V)  ## cplx pwr at "from" bus, p["u"].
    St = V[ branch[:, T_BUS].astype(int) ] * conj(Yt * V)  ## cplx pwr at "to" bus, p["u"].
    branch[:, PF] = Sf.real * baseMVA
    branch[:, QF] = Sf.imag * baseMVA
    branch[:, PT] = St.real * baseMVA
    branch[:, QT] = St.imag * baseMVA

    ## line constraint is actually on square of limit
    ## so we must fix multipliers
    muSf = zeros(nl)
    muSt = zeros(nl)
    if len(il) > 0:
        muSf[il] = \
            2 * lmbda["ineqnonlin"][:nl2] * branch[il, RATE_A] / baseMVA
        muSt[il] = \
            2 * lmbda["ineqnonlin"][nl2:nl2+nl2] * branch[il, RATE_A] / baseMVA

    ## update Lagrange multipliers
    bus[:, MU_VMAX]  = lmbda["upper"][vv["i1"]["Vm"]:vv["iN"]["Vm"]]
    bus[:, MU_VMIN]  = lmbda["lower"][vv["i1"]["Vm"]:vv["iN"]["Vm"]]
    gen[:, MU_PMAX]  = lmbda["upper"][vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
    gen[:, MU_PMIN]  = lmbda["lower"][vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
    gen[:, MU_QMAX]  = lmbda["upper"][vv["i1"]["Qg"]:vv["iN"]["Qg"]] / baseMVA
    gen[:, MU_QMIN]  = lmbda["lower"][vv["i1"]["Qg"]:vv["iN"]["Qg"]] / baseMVA

    bus[:, LAM_P] = \
        lmbda["eqnonlin"][nn["i1"]["Pmis"]:nn["iN"]["Pmis"]] / baseMVA
    bus[:, LAM_Q] = \
        lmbda["eqnonlin"][nn["i1"]["Qmis"]:nn["iN"]["Qmis"]] / baseMVA
    branch[:, MU_SF] = muSf / baseMVA
    branch[:, MU_ST] = muSt / baseMVA

    ## package up results
    nlnN = om.getN('nln')

    ## extract multipliers for nonlinear constraints
    kl = find(lmbda["eqnonlin"] < 0)
    ku = find(lmbda["eqnonlin"] > 0)
    nl_mu_l = zeros(nlnN)
    nl_mu_u = r_[zeros(2*nb), muSf, muSt]
    nl_mu_l[kl] = -lmbda["eqnonlin"][kl]
    nl_mu_u[ku] =  lmbda["eqnonlin"][ku]

    mu = {
      'var': {'l': lmbda["lower"], 'u': lmbda["upper"]},
      'nln': {'l': nl_mu_l, 'u': nl_mu_u},
      'lin': {'l': lmbda["mu_l"], 'u': lmbda["mu_u"]} }

    results = ppc
    results["bus"], results["branch"], results["gen"], \
        results["om"], results["x"], results["mu"], results["f"] = \
            bus, branch, gen, om, x, mu, f

    pimul = r_[
        results["mu"]["nln"]["l"] - results["mu"]["nln"]["u"],
        results["mu"]["lin"]["l"] - results["mu"]["lin"]["u"],
        -ones(ny > 0),
        results["mu"]["var"]["l"] - results["mu"]["var"]["u"],
    ]
    raw = {'xr': x, 'pimul': pimul, 'info': info, 'output': output}

    return results, success, raw
示例#48
0
def makeBdc(baseMVA, bus, branch):
    """Builds the B matrices and phase shift injections for DC power flow.

    Returns the B matrices and phase shift injection vectors needed for a
    DC power flow.
    The bus real power injections are related to bus voltage angles by::
        P = Bbus * Va + PBusinj
    The real power flows at the from end the lines are related to the bus
    voltage angles by::
        Pf = Bf * Va + Pfinj
    Does appropriate conversions to p.u.

    @see: L{dcpf}

    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ## constants
    nb = bus.shape[0]          ## number of buses
    nl = branch.shape[0]       ## number of lines

    ## check that bus numbers are equal to indices to bus (one set of bus nums)
    if any(bus[:, BUS_I] != range(nb)):
        stderr.write('makeBdc: buses must be numbered consecutively in '
                     'bus matrix\n')

    ## for each branch, compute the elements of the branch B matrix and the phase
    ## shift "quiescent" injections, where
    ##
    ##      | Pf |   | Bff  Bft |   | Vaf |   | Pfinj |
    ##      |    | = |          | * |     | + |       |
    ##      | Pt |   | Btf  Btt |   | Vat |   | Ptinj |
    ##
    stat = branch[:, BR_STATUS]               ## ones at in-service branches
    b = stat / branch[:, BR_X]                ## series susceptance
    tap = ones(nl)                            ## default tap ratio = 1
    i = find(branch[:, TAP])               ## indices of non-zero tap ratios
    tap[i] = branch[i, TAP]                   ## assign non-zero tap ratios
    b = b / tap

    ## build connection matrix Cft = Cf - Ct for line and from - to buses
    f = branch[:, F_BUS]                           ## list of "from" buses
    t = branch[:, T_BUS]                           ## list of "to" buses
    i = r_[range(nl), range(nl)]                   ## double set of row indices
    ## connection matrix
    Cft = sparse((r_[ones(nl), -ones(nl)], (i, r_[f, t])), (nl, nb))

    ## build Bf such that Bf * Va is the vector of real branch powers injected
    ## at each branch's "from" bus
    Bf = sparse((r_[b, -b], (i, r_[f, t])))## = spdiags(b, 0, nl, nl) * Cft

    ## build Bbus
    Bbus = Cft.T * Bf

    ## build phase shift injection vectors
    Pfinj = b * (-branch[:, SHIFT] * pi / 180)  ## injected at the from bus ...
    # Ptinj = -Pfinj                            ## and extracted at the to bus
    Pbusinj = Cft.T * Pfinj                ## Pbusinj = Cf * Pfinj + Ct * Ptinj

    return Bbus, Bf, Pbusinj, Pfinj
示例#49
0
def ext2int(ppc, val_or_field=None, ordering=None, dim=0):
    """Converts external to internal indexing.

    This function has two forms, the old form that operates on
    and returns individual matrices and the new form that operates
    on and returns an entire PYPOWER case dict.

    1.  C{ppc = ext2int(ppc)}

    If the input is a single PYPOWER case dict, then all isolated
    buses, off-line generators and branches are removed along with any
    generators, branches or areas connected to isolated buses. Then the
    buses are renumbered consecutively, beginning at 0, and the
    generators are sorted by increasing bus number. Any 'ext2int'
    callback routines registered in the case are also invoked
    automatically. All of the related
    indexing information and the original data matrices are stored under
    the 'order' key of the dict to be used by C{int2ext} to perform
    the reverse conversions. If the case is already using internal
    numbering it is returned unchanged.

    Example::
        ppc = ext2int(ppc)

    @see: L{int2ext}, L{e2i_field}, L{e2i_data}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ppc = deepcopy(ppc)
    if val_or_field is None:  # nargin == 1
        first = 'order' not in ppc
        if first or ppc["order"]["state"] == 'e':
            ## initialize order
            if first:
                o = {
                        'ext':      {
                                'bus':      None,
                                'branch':   None,
                                'gen':      None
                            },
                        'bus':      { 'e2i':      None,
                                      'i2e':      None,
                                      'status':   {} },
                        'gen':      { 'e2i':      None,
                                      'i2e':      None,
                                      'status':   {} },
                        'branch':   { 'status': {} }
                    }
            else:
                o = ppc["order"]

            ## sizes
            nb = ppc["bus"].shape[0]
            ng = ppc["gen"].shape[0]
            ng0 = ng
            if 'A' in ppc:
                dc = True if ppc["A"].shape[1] < (2 * nb + 2 * ng) else False
            elif 'N' in ppc:
                dc = True if ppc["N"].shape[1] < (2 * nb + 2 * ng) else False
            else:
                dc = False

            ## save data matrices with external ordering
            if 'ext' not in o: o['ext'] = {}
            o["ext"]["bus"]    = ppc["bus"].copy()
            o["ext"]["branch"] = ppc["branch"].copy()
            o["ext"]["gen"]    = ppc["gen"].copy()
            if 'areas' in ppc:
                if len(ppc["areas"]) == 0: ## if areas field is empty
                    del ppc['areas']       ## delete it (so it's ignored)
                else:                      ## otherwise
                    o["ext"]["areas"] = ppc["areas"].copy()  ## save it

            ## check that all buses have a valid BUS_TYPE
            bt = ppc["bus"][:, BUS_TYPE]
            err = find(~((bt == PQ) | (bt == PV) | (bt == REF) | (bt == NONE)))
            if len(err) > 0:
                sys.stderr.write('ext2int: bus %d has an invalid BUS_TYPE\n' % err)

            ## determine which buses, branches, gens are connected and
            ## in-service
            n2i = sparse((range(nb), (ppc["bus"][:, BUS_I], zeros(nb))),
                         shape=(max(ppc["bus"][:, BUS_I]) + 1, 1))
            n2i = array( n2i.todense().flatten() )[0, :] # as 1D array
            bs = (bt != NONE)                               ## bus status
            o["bus"]["status"]["on"]  = find(  bs )         ## connected
            o["bus"]["status"]["off"] = find( ~bs )         ## isolated
            gs = ( (ppc["gen"][:, GEN_STATUS] > 0) &          ## gen status
                    bs[ n2i[ppc["gen"][:, GEN_BUS].astype(int)] ] )
            o["gen"]["status"]["on"]  = find(  gs )    ## on and connected
            o["gen"]["status"]["off"] = find( ~gs )    ## off or isolated
            brs = ( ppc["branch"][:, BR_STATUS].astype(int) &  ## branch status
                    bs[n2i[ppc["branch"][:, F_BUS].astype(int)]] &
                    bs[n2i[ppc["branch"][:, T_BUS].astype(int)]] ).astype(bool)
            o["branch"]["status"]["on"]  = find(  brs ) ## on and conn
            o["branch"]["status"]["off"] = find( ~brs )
            if 'areas' in ppc:
                ar = bs[ n2i[ppc["areas"][:, PRICE_REF_BUS].astype(int)] ]
                o["areas"] = {"status": {}}
                o["areas"]["status"]["on"]  = find(  ar )
                o["areas"]["status"]["off"] = find( ~ar )

            ## delete stuff that is "out"
            if len(o["bus"]["status"]["off"]) > 0:
#                ppc["bus"][o["bus"]["status"]["off"], :] = array([])
                ppc["bus"] = ppc["bus"][o["bus"]["status"]["on"], :]
            if len(o["branch"]["status"]["off"]) > 0:
#                ppc["branch"][o["branch"]["status"]["off"], :] = array([])
                ppc["branch"] = ppc["branch"][o["branch"]["status"]["on"], :]
            if len(o["gen"]["status"]["off"]) > 0:
#                ppc["gen"][o["gen"]["status"]["off"], :] = array([])
                ppc["gen"] = ppc["gen"][o["gen"]["status"]["on"], :]
            if 'areas' in ppc and (len(o["areas"]["status"]["off"]) > 0):
#                ppc["areas"][o["areas"]["status"]["off"], :] = array([])
                ppc["areas"] = ppc["areas"][o["areas"]["status"]["on"], :]

            ## update size
            nb = ppc["bus"].shape[0]

            ## apply consecutive bus numbering
            o["bus"]["i2e"] = ppc["bus"][:, BUS_I].copy()
            o["bus"]["e2i"] = zeros(max(o["bus"]["i2e"]) + 1)
            o["bus"]["e2i"][o["bus"]["i2e"].astype(int)] = arange(nb)

            ppc["bus"][:, BUS_I] = \
                o["bus"]["e2i"][ ppc["bus"][:, BUS_I].astype(int) ].copy()


            ppc["gen"][:, GEN_BUS] = \
                o["bus"]["e2i"][ ppc["gen"][:, GEN_BUS].astype(int) ].copy()
            ppc["branch"][:, F_BUS] = \
                o["bus"]["e2i"][ ppc["branch"][:, F_BUS].astype(int) ].copy()
            ppc["branch"][:, T_BUS] = \
                o["bus"]["e2i"][ ppc["branch"][:, T_BUS].astype(int) ].copy()
            if 'areas' in ppc:
                ppc["areas"][:, PRICE_REF_BUS] = \
                    o["bus"]["e2i"][ ppc["areas"][:,
                        PRICE_REF_BUS].astype(int) ].copy()

            ## reorder gens in order of increasing bus number
            o["gen"]["e2i"] = argsort(ppc["gen"][:, GEN_BUS])
            o["gen"]["i2e"] = argsort(o["gen"]["e2i"])

            ppc["gen"] = ppc["gen"][o["gen"]["e2i"].astype(int), :]

            if 'int' in o:
                del o['int']
            o["state"] = 'i'
            ppc["order"] = o

            ## update gencost, A and N
            if 'gencost' in ppc:
                ordering = ['gen']            ## Pg cost only
                if ppc["gencost"].shape[0] == (2 * ng0):
                    ordering.append('gen')    ## include Qg cost
                ppc = e2i_field(ppc, 'gencost', ordering)
            if 'A' in ppc or 'N' in ppc:
                if dc:
                    ordering = ['bus', 'gen']
                else:
                    ordering = ['bus', 'bus', 'gen', 'gen']
            if 'A' in ppc:
                ppc = e2i_field(ppc, 'A', ordering, 1)
            if 'N' in ppc:
                ppc = e2i_field(ppc, 'N', ordering, 1)

            ## execute userfcn callbacks for 'ext2int' stage
            if 'userfcn' in ppc:
                ppc = run_userfcn(ppc['userfcn'], 'ext2int', ppc)
    else:                    ## convert extra data
        if isinstance(val_or_field, str) or isinstance(val_or_field, list):
            ## field
            warn('Calls of the form ppc = ext2int(ppc, '
                '\'field_name\', ...) have been deprecated. Please '
                'replace ext2int with e2i_field.', DeprecationWarning)
            gen, branch = val_or_field, ordering
            ppc = e2i_field(ppc, gen, branch, dim)

        else:
            ## value
            warn('Calls of the form val = ext2int(ppc, val, ...) have been '
                 'deprecated. Please replace ext2int with e2i_data.',
                 DeprecationWarning)
            gen, branch = val_or_field, ordering
            ppc = e2i_data(ppc, gen, branch, dim)

    return ppc
示例#50
0
def qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt):
    """Quadratic Program Solver based on IPOPT.

    Uses IPOPT to solve the following QP (quadratic programming) problem::

        min 1/2 x'*H*x + c'*x
         x

    subject to::

        l <= A*x <= u       (linear constraints)
        xmin <= x <= xmax   (variable bounds)

    Inputs (all optional except C{H}, C{C}, C{A} and C{L}):
        - C{H} : matrix (possibly sparse) of quadratic cost coefficients
        - C{C} : vector of linear cost coefficients
        - C{A, l, u} : define the optional linear constraints. Default
        values for the elements of C{l} and C{u} are -Inf and Inf,
        respectively.
        - C{xmin, xmax} : optional lower and upper bounds on the
        C{x} variables, defaults are -Inf and Inf, respectively.
        - C{x0} : optional starting value of optimization vector C{x}
        - C{opt} : optional options structure with the following fields,
        all of which are also optional (default values shown in parentheses)
            - C{verbose} (0) - controls level of progress output displayed
                - 0 = no progress output
                - 1 = some progress output
                - 2 = verbose progress output
            - C{max_it} (0) - maximum number of iterations allowed
                - 0 = use algorithm default
            - C{ipopt_opt} - options struct for IPOPT, values in
            C{verbose} and C{max_it} override these options
        - C{problem} : The inputs can alternatively be supplied in a single
        C{problem} dict with fields corresponding to the input arguments
        described above: C{H, c, A, l, u, xmin, xmax, x0, opt}

    Outputs:
        - C{x} : solution vector
        - C{f} : final objective function value
        - C{exitflag} : exit flag
            - 1 = first order optimality conditions satisfied
            - 0 = maximum number of iterations reached
            - -1 = numerically failed
        - C{output} : output struct with the following fields:
            - C{iterations} - number of iterations performed
            - C{hist} - dict list with trajectories of the following:
            C{feascond}, C{gradcond}, C{compcond}, C{costcond}, C{gamma},
            C{stepsize}, C{obj}, C{alphap}, C{alphad}
            - message - exit message
        - C{lmbda} : dict containing the Langrange and Kuhn-Tucker
        multipliers on the constraints, with fields:
            - C{mu_l} - lower (left-hand) limit on linear constraints
            - C{mu_u} - upper (right-hand) limit on linear constraints
            - C{lower} - lower bound on optimization variables
            - C{upper} - upper bound on optimization variables

    Calling syntax options::
        x, f, exitflag, output, lmbda = \
            qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt)

        x = qps_ipopt(H, c, A, l, u)
        x = qps_ipopt(H, c, A, l, u, xmin, xmax)
        x = qps_ipopt(H, c, A, l, u, xmin, xmax, x0)
        x = qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt)
        x = qps_ipopt(problem), where problem is a struct with fields:
                        H, c, A, l, u, xmin, xmax, x0, opt
                        all fields except 'c', 'A' and 'l' or 'u' are optional
        x = qps_ipopt(...)
        x, f = qps_ipopt(...)
        x, f, exitflag = qps_ipopt(...)
        x, f, exitflag, output = qps_ipopt(...)
        x, f, exitflag, output, lmbda = qps_ipopt(...)

    Example::
        H = [   1003.1  4.3     6.3     5.9;
                4.3     2.2     2.1     3.9;
                6.3     2.1     3.5     4.8;
                5.9     3.9     4.8     10  ]
        c = zeros((4, 1))
        A = [   1       1       1       1
                0.17    0.11    0.10    0.18    ]
        l = [1, 0.10]
        u = [1, Inf]
        xmin = zeros((4, 1))
        x0 = [1, 0, 0, 1]
        opt = {'verbose': 2)
        x, f, s, out, lambda = qps_ipopt(H, c, A, l, u, xmin, [], x0, opt)

    Problem from U{http://www.jmu.edu/docs/sasdoc/sashtml/iml/chap8/sect12.htm}

    @see: C{pyipopt}, L{ipopt_options}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ##----- input argument handling  -----
    ## gather inputs
    if isinstance(H, dict):       ## problem struct
        p = H
        if 'opt' in p: opt = p['opt']
        if 'x0' in p: x0 = p['x0']
        if 'xmax' in p: xmax = p['xmax']
        if 'xmin' in p: xmin = p['xmin']
        if 'u' in p: u = p['u']
        if 'l' in p: l = p['l']
        if 'A' in p: A = p['A']
        if 'c' in p: c = p['c']
        if 'H' in p: H = p['H']
    else:                         ## individual args
        assert H is not None
        assert c is not None
        assert A is not None
        assert l is not None

    if opt is None:
        opt = {}
#    if x0 is None:
#        x0 = array([])
#    if xmax is None:
#        xmax = array([])
#    if xmin is None:
#        xmin = array([])

    ## define nx, set default values for missing optional inputs
    if len(H) == 0 or not any(any(H)):
        if len(A) == 0 and len(xmin) == 0 and len(xmax) == 0:
            stderr.write('qps_ipopt: LP problem must include constraints or variable bounds\n')
        else:
            if len(A) > 0:
                nx = shape(A)[1]
            elif len(xmin) > 0:
                nx = len(xmin)
            else:    # if len(xmax) > 0
                nx = len(xmax)
        H = sparse((nx, nx))
    else:
        nx = shape(H)[0]

    if len(c) == 0:
        c = zeros(nx)

    if  len(A) > 0 and (len(l) == 0 or all(l == -Inf)) and \
                       (len(u) == 0 or all(u ==  Inf)):
        A = None                    ## no limits => no linear constraints

    nA = shape(A)[0]                ## number of original linear constraints
    if nA:
        if len(u) == 0:             ## By default, linear inequalities are ...
            u = Inf * ones(nA)      ## ... unbounded above and ...

        if len(l) == 0:
            l = -Inf * ones(nA)     ## ... unbounded below.

    if len(x0) == 0:
        x0 = zeros(nx)

    ## default options
    if 'verbose' in opt:
        verbose = opt['verbose']
    else:
        verbose = 0

    if 'max_it' in opt:
        max_it = opt['max_it']
    else:
        max_it = 0

    ## make sure args are sparse/full as expected by IPOPT
    if len(H) > 0:
        if not issparse(H):
            H = sparse(H)

    if not issparse(A):
        A = sparse(A)

    ##-----  run optimization  -----
    ## set options dict for IPOPT
    options = {}
    if 'ipopt_opt' in opt:
        options['ipopt'] = ipopt_options(opt['ipopt_opt'])
    else:
        options['ipopt'] = ipopt_options()

    options['ipopt']['jac_c_constant']    = 'yes'
    options['ipopt']['jac_d_constant']    = 'yes'
    options['ipopt']['hessian_constant']  = 'yes'
    options['ipopt']['least_square_init_primal']  = 'yes'
    options['ipopt']['least_square_init_duals']   = 'yes'
    # options['ipopt']['mehrotra_algorithm']        = 'yes'     ## default 'no'
    if verbose:
        options['ipopt']['print_level'] = min(12, verbose * 2 + 1)
    else:
        options['ipopt']['print_level = 0']

    if max_it:
        options['ipopt']['max_iter'] = max_it

    ## define variable and constraint bounds, if given
    if nA:
        options['cu'] = u
        options['cl'] = l

    if len(xmin) > 0:
        options['lb'] = xmin

    if len(xmax) > 0:
        options['ub'] = xmax

    ## assign function handles
    funcs = {}
    funcs['objective']         = lambda x: 0.5 * x.T * H * x + c.T * x
    funcs['gradient']          = lambda x: H * x + c
    funcs['constraints']       = lambda x: A * x
    funcs['jacobian']          = lambda x: A
    funcs['jacobianstructure'] = lambda : A
    funcs['hessian']           = lambda x, sigma, lmbda: tril(H)
    funcs['hessianstructure']  = lambda : tril(H)

    ## run the optimization
    x, info = pyipopt(x0, funcs, options)

    if info['status'] == 0 | info['status'] == 1:
        eflag = 1
    else:
        eflag = 0

    output = {}
    if 'iter' in info:
        output['iterations'] = info['iter']

    output['info']       = info['status']
    f = funcs['objective'](x)

    ## repackage lmbdas
    kl = find(info['lmbda'] < 0)                     ## lower bound binding
    ku = find(info['lmbda'] > 0)                     ## upper bound binding
    mu_l = zeros(nA)
    mu_l[kl] = -info['lmbda'][kl]
    mu_u = zeros(nA)
    mu_u[ku] = info['lmbda'][ku]

    lmbda = {
        'mu_l': mu_l,
        'mu_u': mu_u,
        'lower': info['zl'],
        'upper': info['zu']
    }

    return x, f, eflag, output, lmbda
示例#51
0
def pfsoln(baseMVA, bus0, gen0, branch0, Ybus, Yf, Yt, V, ref, pv, pq):
    """Updates bus, gen, branch data structures to match power flow soln.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ## initialize return values
    bus     = bus0
    gen     = gen0
    branch  = branch0

    ##----- update bus voltages -----
    bus[:, VM] = abs(V)
    bus[:, VA] = angle(V) * 180 / pi

    ##----- update Qg for all gens and Pg for slack bus(es) -----
    ## generator info
    on = find(gen[:, GEN_STATUS] > 0) ## which generators are on?
    gbus = gen[on, GEN_BUS].astype(int)  ## what buses are they at?

    ## compute total injected bus powers
    Sbus = V[gbus] * conj(Ybus[gbus, :] * V)

    ## update Qg for all generators
    gen[:, QG] = zeros(gen.shape[0])              ## zero out all Qg
    gen[on, QG] = Sbus.imag * baseMVA + bus[gbus, QD]    ## inj Q + local Qd
    ## ... at this point any buses with more than one generator will have
    ## the total Q dispatch for the bus assigned to each generator. This
    ## must be split between them. We do it first equally, then in proportion
    ## to the reactive range of the generator.

    if len(on) > 1:
        ## build connection matrix, element i, j is 1 if gen on(i) at bus j is ON
        nb = bus.shape[0]
        ngon = on.shape[0]
        Cg = csr_matrix((ones(ngon), (range(ngon), gbus)), (ngon, nb))

        ## divide Qg by number of generators at the bus to distribute equally
        ngg = Cg * Cg.sum(0).T    ## ngon x 1, number of gens at this gen's bus
        ngg = asarray(ngg).flatten()  # 1D array
        gen[on, QG] = gen[on, QG] / ngg

        ## divide proportionally
        Cmin = csr_matrix((gen[on, QMIN], (range(ngon), gbus)), (ngon, nb))
        Cmax = csr_matrix((gen[on, QMAX], (range(ngon), gbus)), (ngon, nb))
        Qg_tot = Cg.T * gen[on, QG]## nb x 1 vector of total Qg at each bus
        Qg_min = Cmin.sum(0).T       ## nb x 1 vector of min total Qg at each bus
        Qg_max = Cmax.sum(0).T       ## nb x 1 vector of max total Qg at each bus
        Qg_min = asarray(Qg_min).flatten()  # 1D array
        Qg_max = asarray(Qg_max).flatten()  # 1D array
        ## gens at buses with Qg range = 0
        ig = find(Cg * Qg_min == Cg * Qg_max)
        Qg_save = gen[on[ig], QG]
        gen[on, QG] = gen[on, QMIN] + \
            (Cg * ((Qg_tot - Qg_min) / (Qg_max - Qg_min + EPS))) * \
                (gen[on, QMAX] - gen[on, QMIN])    ##    ^ avoid div by 0
        gen[on[ig], QG] = Qg_save  ## (terms are mult by 0 anyway)

    ## update Pg for slack bus(es)
    ## inj P + local Pd
    for k in range(len(ref)):
        refgen = find(gbus == ref[k])  ## which is(are) the reference gen(s)?
        gen[on[refgen[0]], PG] = \
                Sbus[refgen[0]].real * baseMVA + bus[ref[k], PD]
        if len(refgen) > 1:       ## more than one generator at this ref bus
            ## subtract off what is generated by other gens at this bus
            gen[on[refgen[0]], PG] = \
                gen[on[refgen[0]], PG] - sum(gen[on[refgen[1:len(refgen)]], PG])

    ##----- update/compute branch power flows -----
    out = find(branch[:, BR_STATUS] == 0)        ## out-of-service branches
    br =  find(branch[:, BR_STATUS]).astype(int) ## in-service branches

    ## complex power at "from" bus
    Sf = V[ branch[br, F_BUS].astype(int) ] * conj(Yf[br, :] * V) * baseMVA
    ## complex power injected at "to" bus
    St = V[ branch[br, T_BUS].astype(int) ] * conj(Yt[br, :] * V) * baseMVA
    branch[ ix_(br, [PF, QF, PT, QT]) ] = c_[Sf.real, Sf.imag, St.real, St.imag]
    branch[ ix_(out, [PF, QF, PT, QT]) ] = zeros((len(out), 4))

    return bus, gen, branch
def ipoptopf_solver(om, ppopt):
    """Solves AC optimal power flow using IPOPT.

    Inputs are an OPF model object and a PYPOWER options vector.

    Outputs are a C{results} dict, C{success} flag and C{raw} output dict.

    C{results} is a PYPOWER case dict (ppc) with the usual C{baseMVA}, C{bus}
    C{branch}, C{gen}, C{gencost} fields, along with the following additional
    fields:
        - C{order}      see 'help ext2int' for details of this field
        - C{x}          final value of optimization variables (internal order)
        - C{f}          final objective function value
        - C{mu}         shadow prices on ...
            - C{var}
                - C{l}  lower bounds on variables
                - C{u}  upper bounds on variables
            - C{nln}
                - C{l}  lower bounds on nonlinear constraints
                - C{u}  upper bounds on nonlinear constraints
            - C{lin}
                - C{l}  lower bounds on linear constraints
                - C{u}  upper bounds on linear constraints

    C{success} is C{True} if solver converged successfully, C{False} otherwise

    C{raw} is a raw output dict in form returned by MINOS
        - C{xr}     final value of optimization variables
        - C{pimul}  constraint multipliers
        - C{info}   solver specific termination code
        - C{output} solver specific output information

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

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    import pyipopt

    ## unpack data
    ppc = om.get_ppc()
    baseMVA, bus, gen, branch, gencost = \
        ppc['baseMVA'], ppc['bus'], ppc['gen'], ppc['branch'], ppc['gencost']
    vv, _, nn, _ = om.get_idx()

    ## problem dimensions
    nb = shape(bus)[0]          ## number of buses
    ng = shape(gen)[0]          ## number of gens
    nl = shape(branch)[0]       ## number of branches
    ny = om.getN('var', 'y')    ## number of piece-wise linear costs

    ## linear constraints
    A, l, u = om.linear_constraints()

    ## bounds on optimization vars
    _, xmin, xmax = om.getv()

    ## build admittance matrices
    Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)

    ## try to select an interior initial point
    ll = xmin.copy(); uu = xmax.copy()
    ll[xmin == -Inf] = -2e19   ## replace Inf with numerical proxies
    uu[xmax ==  Inf] =  2e19
    x0 = (ll + uu) / 2
    Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180)
    x0[vv['i1']['Va']:vv['iN']['Va']] = Varefs[0]  ## angles set to first reference angle
    if ny > 0:
        ipwl = find(gencost[:, MODEL] == PW_LINEAR)
#        PQ = r_[gen[:, PMAX], gen[:, QMAX]]
#        c = totcost(gencost[ipwl, :], PQ[ipwl])
        ## largest y-value in CCV data
        c = gencost.flatten('F')[sub2ind(shape(gencost), ipwl, NCOST + 2 * gencost[ipwl, NCOST])]
        x0[vv['i1']['y']:vv['iN']['y']] = max(c) + 0.1 * abs(max(c))
#        x0[vv['i1']['y']:vv['iN']['y']) = c + 0.1 * abs(c)

    ## find branches with flow limits
    il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
    nl2 = len(il)           ## number of constrained lines

    ##-----  run opf  -----
    ## build Jacobian and Hessian structure
    if A is not None and issparse(A):
        nA = A.shape[0]                ## number of original linear constraints
    else:
        nA = 0
    nx = len(x0)
    f = branch[:, F_BUS]                           ## list of "from" buses
    t = branch[:, T_BUS]                           ## list of "to" buses
    Cf = sparse((ones(nl), (arange(nl), f)), (nl, nb))      ## connection matrix for line & from buses
    Ct = sparse((ones(nl), (arange(nl), t)), (nl, nb))      ## connection matrix for line & to buses
    Cl = Cf + Ct
    Cb = Cl.T * Cl + speye(nb, nb)
    Cl2 = Cl[il, :]
    Cg = sparse((ones(ng), (gen[:, GEN_BUS], arange(ng))), (nb, ng))
    nz = nx - 2 * (nb + ng)
    nxtra = nx - 2 * nb
    if nz > 0:
        Js = vstack([
            hstack([Cb,      Cb,      Cg,              sparse((nb, ng)),   sparse((nb,  nz))]),
            hstack([Cb,      Cb,      sparse((nb, ng)),   Cg,              sparse((nb,  nz))]),
            hstack([Cl2,     Cl2,     sparse((nl2, 2 * ng)),               sparse((nl2, nz))]),
            hstack([Cl2,     Cl2,     sparse((nl2, 2 * ng)),               sparse((nl2, nz))])
        ], 'coo')
    else:
        Js = vstack([
            hstack([Cb,      Cb,      Cg,              sparse((nb, ng))]),
            hstack([Cb,      Cb,      sparse((nb, ng)),   Cg,          ]),
            hstack([Cl2,     Cl2,     sparse((nl2, 2 * ng)),           ]),
            hstack([Cl2,     Cl2,     sparse((nl2, 2 * ng)),           ])
        ], 'coo')

    if A is not None and issparse(A):
        Js = vstack([Js, A], 'coo')

    f, _, d2f = opf_costfcn(x0, om, True)
    Hs = tril(d2f + vstack([
        hstack([Cb,  Cb,  sparse((nb, nxtra))]),
        hstack([Cb,  Cb,  sparse((nb, nxtra))]),
        sparse((nxtra, nx))
    ]), format='coo')

    ## set options struct for IPOPT
#    options = {}
#    options['ipopt'] = ipopt_options([], ppopt)

    ## extra data to pass to functions
    userdata = {
        'om':       om,
        'Ybus':     Ybus,
        'Yf':       Yf[il, :],
        'Yt':       Yt[il, :],
        'ppopt':    ppopt,
        'il':       il,
        'A':        A,
        'nA':       nA,
        'neqnln':   2 * nb,
        'niqnln':   2 * nl2,
        'Js':       Js,
        'Hs':       Hs
    }

    ## check Jacobian and Hessian structure
    #xr                  = rand(x0.shape)
    #lmbda               = rand( 2 * nb + 2 * nl2)
    #Js1 = eval_jac_g(x, flag, userdata) #(xr, options.auxdata)
    #Hs1  = eval_h(xr, 1, lmbda, userdata)
    #i1, j1, s = find(Js)
    #i2, j2, s = find(Js1)
    #if (len(i1) != len(i2)) | (norm(i1 - i2) != 0) | (norm(j1 - j2) != 0):
    #    raise ValueError, 'something''s wrong with the Jacobian structure'
    #
    #i1, j1, s = find(Hs)
    #i2, j2, s = find(Hs1)
    #if (len(i1) != len(i2)) | (norm(i1 - i2) != 0) | (norm(j1 - j2) != 0):
    #    raise ValueError, 'something''s wrong with the Hessian structure'

    ## define variable and constraint bounds
    # n is the number of variables
    n = x0.shape[0]
    # xl is the lower bound of x as bounded constraints
    xl = xmin
    # xu is the upper bound of x as bounded constraints
    xu = xmax

    neqnln = 2 * nb
    niqnln = 2 * nl2

    # number of constraints
    m = neqnln + niqnln + nA
    # lower bound of constraint
    gl = r_[zeros(neqnln), -Inf * ones(niqnln), l]
    # upper bound of constraints
    gu = r_[zeros(neqnln),       zeros(niqnln), u]

    # number of nonzeros in Jacobi matrix
    nnzj = Js.nnz
    # number of non-zeros in Hessian matrix, you can set it to 0
    nnzh = Hs.nnz

    eval_hessian = True
    if eval_hessian:
        hessian = lambda x, lagrange, obj_factor, flag, user_data=None: \
                eval_h(x, lagrange, obj_factor, flag, userdata)

        nlp = pyipopt.create(n, xl, xu, m, gl, gu, nnzj, nnzh,
                             eval_f, eval_grad_f, eval_g, eval_jac_g, hessian)
    else:
        nnzh = 0
        nlp = pyipopt.create(n, xl, xu, m, gl, gu, nnzj, nnzh,
                             eval_f, eval_grad_f, eval_g, eval_jac_g)

    nlp.int_option('print_level', 5)
    nlp.num_option('tol', 1.0000e-12)
    nlp.int_option('max_iter', 250)
    nlp.num_option('dual_inf_tol', 0.10000)
    nlp.num_option('constr_viol_tol', 1.0000e-06)
    nlp.num_option('compl_inf_tol', 1.0000e-05)
    nlp.num_option('acceptable_tol', 1.0000e-08)
    nlp.num_option('acceptable_constr_viol_tol', 1.0000e-04)
    nlp.num_option('acceptable_compl_inf_tol', 0.0010000)
    nlp.str_option('mu_strategy', 'adaptive')

    iter = 0
    def intermediate_callback(algmod, iter_count, obj_value, inf_pr, inf_du,
            mu, d_norm, regularization_size, alpha_du, alpha_pr, ls_trials,
            user_data=None):
        iter = iter_count
        return True

    nlp.set_intermediate_callback(intermediate_callback)

    ## run the optimization
    # returns final solution x, upper and lower bound for multiplier, final
    # objective function obj and the return status of ipopt
    x, zl, zu, obj, status, zg = nlp.solve(x0, m, userdata)

    info = {'x': x, 'zl': zl, 'zu': zu, 'obj': obj, 'status': status, 'lmbda': zg}

    nlp.close()

    success = (status == 0) | (status == 1)

    output = {'iterations': iter}

    f, _ = opf_costfcn(x, om)

    ## update solution data
    Va = x[vv['i1']['Va']:vv['iN']['Va']]
    Vm = x[vv['i1']['Vm']:vv['iN']['Vm']]
    Pg = x[vv['i1']['Pg']:vv['iN']['Pg']]
    Qg = x[vv['i1']['Qg']:vv['iN']['Qg']]
    V = Vm * exp(1j * Va)

    ##-----  calculate return values  -----
    ## update voltages & generator outputs
    bus[:, VA] = Va * 180 / pi
    bus[:, VM] = Vm
    gen[:, PG] = Pg * baseMVA
    gen[:, QG] = Qg * baseMVA
    gen[:, VG] = Vm[gen[:, GEN_BUS].astype(int)]

    ## compute branch flows
    f_br = branch[:, F_BUS].astype(int)
    t_br = branch[:, T_BUS].astype(int)
    Sf = V[f_br] * conj(Yf * V)  ## cplx pwr at "from" bus, p.u.
    St = V[t_br] * conj(Yt * V)  ## cplx pwr at "to" bus, p.u.
    branch[:, PF] = Sf.real * baseMVA
    branch[:, QF] = Sf.imag * baseMVA
    branch[:, PT] = St.real * baseMVA
    branch[:, QT] = St.imag * baseMVA

    ## line constraint is actually on square of limit
    ## so we must fix multipliers
    muSf = zeros(nl)
    muSt = zeros(nl)
    if len(il) > 0:
        muSf[il] = 2 * info['lmbda'][2 * nb +       arange(nl2)] * branch[il, RATE_A] / baseMVA
        muSt[il] = 2 * info['lmbda'][2 * nb + nl2 + arange(nl2)] * branch[il, RATE_A] / baseMVA

    ## update Lagrange multipliers
    bus[:, MU_VMAX]  = info['zu'][vv['i1']['Vm']:vv['iN']['Vm']]
    bus[:, MU_VMIN]  = info['zl'][vv['i1']['Vm']:vv['iN']['Vm']]
    gen[:, MU_PMAX]  = info['zu'][vv['i1']['Pg']:vv['iN']['Pg']] / baseMVA
    gen[:, MU_PMIN]  = info['zl'][vv['i1']['Pg']:vv['iN']['Pg']] / baseMVA
    gen[:, MU_QMAX]  = info['zu'][vv['i1']['Qg']:vv['iN']['Qg']] / baseMVA
    gen[:, MU_QMIN]  = info['zl'][vv['i1']['Qg']:vv['iN']['Qg']] / baseMVA
    bus[:, LAM_P]    = info['lmbda'][nn['i1']['Pmis']:nn['iN']['Pmis']] / baseMVA
    bus[:, LAM_Q]    = info['lmbda'][nn['i1']['Qmis']:nn['iN']['Qmis']] / baseMVA
    branch[:, MU_SF] = muSf / baseMVA
    branch[:, MU_ST] = muSt / baseMVA

    ## package up results
    nlnN = om.getN('nln')

    ## extract multipliers for nonlinear constraints
    kl = find(info['lmbda'][:2 * nb] < 0)
    ku = find(info['lmbda'][:2 * nb] > 0)
    nl_mu_l = zeros(nlnN)
    nl_mu_u = r_[zeros(2 * nb), muSf, muSt]
    nl_mu_l[kl] = -info['lmbda'][kl]
    nl_mu_u[ku] =  info['lmbda'][ku]

    ## extract multipliers for linear constraints
    lam_lin = info['lmbda'][2 * nb + 2 * nl2 + arange(nA)]   ## lmbda for linear constraints
    kl = find(lam_lin < 0)                     ## lower bound binding
    ku = find(lam_lin > 0)                     ## upper bound binding
    mu_l = zeros(nA)
    mu_l[kl] = -lam_lin[kl]
    mu_u = zeros(nA)
    mu_u[ku] = lam_lin[ku]

    mu = {
      'var': {'l': info['zl'], 'u': info['zu']},
      'nln': {'l': nl_mu_l, 'u': nl_mu_u}, \
      'lin': {'l': mu_l, 'u': mu_u}
    }

    results = ppc
    results['bus'], results['branch'], results['gen'], \
        results['om'], results['x'], results['mu'], results['f'] = \
            bus, branch, gen, om, x, mu, f

    pimul = r_[
        results['mu']['nln']['l'] - results['mu']['nln']['u'],
        results['mu']['lin']['l'] - results['mu']['lin']['u'],
        -ones(ny > 0),
        results['mu']['var']['l'] - results['mu']['var']['u']
    ]
    raw = {'xr': x, 'pimul': pimul, 'info': info['status'], 'output': output}

    return results, success, raw
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
示例#54
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
z = scipy.io.loadmat('tmp2');
mi = z['mi']
sx,sy = mi.shape 

#im = plt.imshow(mi, interpolation='bilinear',
#                origin='lower', extent=[1,sx,1,sx])

#plt.savefig('mi.pdf')
#plt.show()
print "MI Loaded"

mi = np.triu(mi)
a = mi.ravel();
print a
level = ss.scoreatpercentile(a,99.)
indexes = np.transpose(np.find(mi<level))
#mi[mi<level]=0

plt.savefig('mi2.pdf')
exit()
print level
print "MI prunned"

G = nx.Graph();
for r in indexes:
#for i in xrange(sx):
    #if i % 100 == 0:
    #    print i
    #for j in xrange(i):
    #    z = mi[i][j]
     #   if z > 0:
def t_auction_pips(quiet=False):
    """Tests for code in auction.py, using PIPS solver.

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

    t_begin(n_tests, quiet)

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

    ppopt = ppoption
    ppopt['OPF_VIOLATION'] = 1e-7
    ppopt['PDIPM_GRADTOL'] = 1e-6
    ppopt['PDIPM_COMPTOL'] = 1e-7
    ppopt['PDIPM_COSTTOL'] = 5e-9
    ppopt['OPF_ALG'] = 560
    ppopt['OUT_ALL_LIM'] = 1
    ppopt['OUT_BRANCH'] = 0
    ppopt['OUT_SYS_SUM'] = 0
    ppopt['OUT_ALL'] = 0
    ppopt['VERBOSE'] = 0
    q = array([
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [12, 24, 24],
        [10, 10, 10],
        [10, 10, 10],
        [10, 10, 10],
    ])

    ##-----  one offer block marginal @ $50  -----
    p = array([
        [20, 50, 60],
        [20, 40, 70],
        [20, 42, 80],
        [20, 44, 90],
        [20, 46, 75],
        [20, 48, 60],
        [100, 70, 60],
        [100, 50, 20],
        [100, 60, 50]
    ])

    t = 'one marginal offer @ $50, auction_type = 5'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
    cq5 = cq.copy()
    cp5 = cp.copy()
    i2e = bus.bus_i
    e2i = sparse((max(i2e), 1))
    e2i[i2e] = range(bus.size())
    G = find( isload(gen) == False )   ## real generators
    L = find( isload(gen) )   ## dispatchable loads
    Gbus = e2i[gen.gen_bus[G]]
    Lbus = e2i[gen.gen_bus[L]]
    Qfudge = zeros(p.shape)
    Qfudge[L, :] = \
        diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L :].shape)

    t_is( cq[G[0], 1:3], [23.32, 0], 2, t )
    t_is( cp[G[0], :], 50, 4, t )
    t_is( cq[L[1], 0:2], [10, 0], 2, t )
    t_is( cp[L[1], :], 54.0312, 4, t )
    t_is( cp[G, 0], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
    t_is( cp[L, 0], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )

    lao_X = p(G[0], 1) / bus.lam_P[Gbus[0], LAM_P]
    fro_X = p(G(5), 2) / bus.lam_P[Gbus[5], LAM_P]
    lab_X = p(L(2), 1) / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
    frb_X = p(L(1), 1) / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])

    t_is( lao_X, 1, 4, 'lao_X')
    t_is( fro_X, 1.1324, 4, 'fro_X')
    t_is( lab_X, 1.0787, 4, 'lab_X')
    t_is( frb_X, 0.9254, 4, 'frb_X')

    t = 'one marginal offer @ $50, auction_type = 1'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1110, 100, [], [], mpopt)
    cp1 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 6, [t, ' : prices'] )

    t = 'one marginal offer @ $50, auction_type = 2'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1120, 100, [], [], mpopt)
    cp2 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp5[G, :] * fro_X, 8, [t, ' : gen prices'] )
    t_is( cp[L[0:1], :], cp5[L[0:1], :] * fro_X, 8, [t, ' : load 1,2 prices'] )
    t_is( cp[L[2], :], 60, 5, [t, ' : load 3 price'] )   ## clipped by accepted bid

    t = 'one marginal offer @ $50, auction_type = 3'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1130, 100, [], [], mpopt)
    cp3 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5 * lab_X, 8, [t, ' : prices'] )

    t = 'one marginal offer @ $50, auction_type = 4'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1140, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], p[G[0], 1], 8, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp5[G[1:6], :] * frb_X, 8, [t, ' : gen 2-6 prices'] )
    t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )

    t = 'one marginal offer @ $50, auction_type = 6'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp3, 8, [t, ' : prices'] )
    p2 = p.copy()
    p2[L, :] = array([
        [100, 100, 100],
        [100,   0,   0],
        [100, 100,   0]
    ])
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 5, [t, ' : quantities'] )
    t_is( cp[G, :], cp5[G, :] * fro_X, 4, [t, ' : gen prices'] )
    t_is( cp[L, :], cp5[L, :] * fro_X, 4, [t, ' : load prices'] ) ## load 3 not clipped as in FRO

    t = 'one marginal offer @ $50, auction_type = 7'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1170, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5 * (lao_X + lab_X) / 2, 8, [t, ' : prices'] )
    t_is( cp, (cp1 + cp3) / 2, 8, [t, ' : prices'] )

    t = 'one marginal offer @ $50, auction_type = 8'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1180, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp1[G, :], 8, [t, ' : gen prices'] )
    t_is( cp[L, :], cp3[L, :], 8, [t, ' : load prices'] )

    t = 'one marginal offer @ $50, auction_type = 0'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1100, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, p, 8, [t, ' : prices'] )


    ##-----  one bid block marginal @ $55  -----
    p[L[1], 1] = 55
    t = 'one marginal bid @ $55, auction_type = 5'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
    cq5 = cq.copy()
    cp5 = cp.copy()
    Qfudge =  zeros(p.shape)
    Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)

    t_is( cq[G[0], 1:3], [24, 0], 2, t )
    t_is( cp[G[0], :], 50.016, 3, t )
    t_is( cq[L[1], 0:2], [10, 0.63], 2, t )
    t_is( cp[L[1], :], 55, 4, t )
    t_is( cp[G, 0], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
    t_is( cp[L, 0], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )

    lao_X = p[G[0], 1] / bus.lam_P[Gbus[0]]
    fro_X = p[G[5], 2] / bus.lam_P[Gbus[5]]
    lab_X = p[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
    frb_X = p[L[2], 2] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])

    t_is( lao_X, 0.9997, 4, 'lao_X')
    t_is( fro_X, 1.1111, 4, 'fro_X')
    t_is( lab_X, 1, 4, 'lab_X')
    t_is( frb_X, 0.8960, 4, 'frb_X')

    t = 'one marginal bid @ $55, auction_type = 1'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1110, 100, [], [], mpopt)
    cp1 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5 * lao_X, 8, [t, ' : prices'] )

    t = 'one marginal bid @ $55, auction_type = 2'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1120, 100, [], [], mpopt)
    cp2 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp5[G, :] * fro_X, 8, [t, ' : gen prices'] )
    t_is( cp[L[0], :], cp5[L[0], :] * fro_X, 8, [t, ' : load 1 price'] )
    t_is( cp[L[1], :], 55, 5, [t, ' : load 2 price'] )
    t_is( cp[L[2], :], 60, 5, [t, ' : load 3 price'] )

    t = 'one marginal bid @ $55, auction_type = 3'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1130, 100, [], [], mpopt)
    cp3 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 7, [t, ' : prices'] )

    t = 'one marginal bid @ $55, auction_type = 4'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1140, 100, [], [], mpopt)
    cp4 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 50, 5, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp5[G[1:6], :] * frb_X, 8, [t, ' : gen 2-6 prices'] )
    t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )

    t = 'one marginal bid @ $55, auction_type = 6'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp1, 8, [t, ' : prices'] )

    p2 = p.copy()
    p2[G, :] = array([
        [0, 0, 100],
        [0, 0, 100],
        [0, 0, 100],
        [0, 0, 100],
        [0, 0, 100],
        [0, 0, 100]
    ])
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 3, [t, ' : quantities'] )
    t_is( cp[G, :], cp5[G, :] * frb_X, 3, [t, ' : gen prices'] )  ## gen 1, not clipped this time
    t_is( cp[L, :], cp4[L, :], 3, [t, ' : load prices'] )

    t = 'one marginal bid @ $55, auction_type = 7'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1170, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5 * (lao_X + lab_X) / 2, 8, [t, ' : prices'] )
    t_is( cp, (cp1 + cp3) / 2, 8, [t, ' : prices'] )

    t = 'one marginal bid @ $55, auction_type = 8'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1180, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp1[G, :], 8, [t, ' : gen prices'] )
    t_is( cp[L, :], cp3[L, :], 8, [t, ' : load prices'] )

    t = 'one marginal bid @ $55, auction_type = 0'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1100, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, p, 8, [t, ' : prices'] )


    ##-----  one bid block marginal @ $54.50 and one offer block marginal @ $50  -----
    p[L[1], 1] = 54.5
    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 5'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
    cq5 = cq.copy()
    cp5 = cp.copy()
    Qfudge =  zeros(p.shape)
    Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)

    t_is( cq[G[0], 1:3], [23.74, 0], 2, t )
    t_is( cp[G[0], :], 50, 4, t )
    t_is( cq[L[1], 0:2], [10, 0.39], 2, t )
    t_is( cp[L[1], :], 54.5, 4, t )
    t_is( cp[G, 0], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
    t_is( cp[L, 0], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )

    lao_X = p[G[0], 1] / bus.lam_P[Gbus[0]]
    fro_X = p[G[5], 2] / bus.lam_P[Gbus[5]]
    lab_X = p[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])
    frb_X = p[L[2], 2] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])

    t_is( lao_X, 1, 4, 'lao_X')
    t_is( fro_X, 1.1221, 4, 'fro_X')
    t_is( lab_X, 1, 4, 'lab_X')
    t_is( frb_X, 0.8976, 4, 'frb_X')

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 1'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1110, 100, [], [], mpopt)
    cp1 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 4, [t, ' : prices'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 2'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1120, 100, [], [], mpopt)
    cp2 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp5[G, :] * fro_X, 5, [t, ' : gen prices'] )
    t_is( cp[L[0], :], cp5[L[0], :] * fro_X, 5, [t, ' : load 1 price'] )
    t_is( cp[L[1], :], 54.5, 5, [t, ' : load 2 price'] )
    t_is( cp[L[2], :], 60, 5, [t, ' : load 3 price'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 3'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1130, 100, [], [], mpopt)
    cp3 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 6, [t, ' : prices'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 4'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1140, 100, [], [], mpopt)
    cp4 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 50, 5, [t, ' : gen 1 price'] )
    t_is( cp[G[1:5], :], cp5[G[1:5], :] * frb_X, 8, [t, ' : gen 2-5 prices'] )
    t_is( cp[G[5], :], 48, 5, [t, ' : gen 6 price'] )
    t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 6'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 4, [t, ' : prices'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 7'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1170, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 4, [t, ' : prices'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 8'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1180, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 4, [t, ' : prices'] )

    t = 'marginal offer @ $50, bid @ $54.50, auction_type = 0'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1100, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, p, 8, [t, ' : prices'] )


    ##-----  gen 1 at Pmin, load 3 block 2 marginal @ $60  -----
    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 5'
    p[L[1], 1] = 50     ## undo previous change
    p2 = p.copy()
    p2[G[0], 1:3] = [65, 65]
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1150, 100, [], [], mpopt)
    Qfudge =  zeros(p.shape)
    Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)

    t_is( cp[G[0], :], 65, 4, [t, ' : gen 1 price'] )
    t_is( cp[G[1], :], 54.2974, 4, [t, ' : gen 2 price'] )
    cq5 = cq.copy()
    cp5 = cp.copy()
    cp_lam = cp5.copt()
    cp_lam[0, :] = bus.lam_P[Gbus[0]]  ## unclipped

    lao_X = p2[G[5], 1] / bus.lam_P[Gbus[5]]
    fro_X = p2[G[5], 2] / bus.lam_P[Gbus[5]]
    lab_X = p2[L[2], 1] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
    frb_X = p2[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])

    t_is( lao_X, 0.8389, 4, 'lao_X')
    t_is( fro_X, 1.0487, 4, 'fro_X')
    t_is( lab_X, 1, 4, 'lab_X')
    t_is( frb_X, 0.8569, 4, 'frb_X')

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 1'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1110, 100, [], [], mpopt)
    cp1 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 65, 8, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp_lam[G[1:6], :] * lao_X, 8, [t, ' : gen 2-6 prices'] )
    t_is( cp[L, :], cp_lam[L, :] * lao_X, 8, [t, ' : load prices'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 2'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1120, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 65, 8, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp_lam[G[1:6], :] * fro_X, 8, [t, ' : gen 2-6 prices'] )
    t_is( cp[L[0:2], :], cp_lam[L[0:2], :] * fro_X, 8, [t, ' : load 1-2 prices'] )
    t_is( cp[L[2], :], 60, 8, [t, ' : load 3 price'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 3'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1130, 100, [], [], mpopt)
    cp3 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 65, 8, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp_lam[G[1:6], :], 6, [t, ' : gen 2-6 prices'] )
    t_is( cp[L, :], cp_lam[L, :], 6, [t, ' : load prices'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 4'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1140, 100, [], [], mpopt)
    cp4 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 65, 5, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp5[G[1:6], :] * frb_X, 8, [t, ' : gen 2-6 prices'] )
    t_is( cp[L, :], cp5[L, :] * frb_X, 8, [t, ' : load prices'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 6'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp4, 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 7'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1170, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G[0], :], 65, 4, [t, ' : gen 1 price'] )
    t_is( cp[G[1:6], :], cp_lam[G[1:6], :] * (lao_X + lab_X) / 2, 8, [t, ' : gen 2-6 prices'] )
    t_is( cp[L, :], cp_lam[L, :] * (lao_X + lab_X) / 2, 8, [t, ' : load prices'] )
    t_is( cp, (cp1 + cp3) / 2, 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 8'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1180, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp1[G, :], 8, [t, ' : prices'] )
    t_is( cp[L, :], cp3[L, :], 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal bid @ $60, auction_type = 0'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1100, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, p2, 8, [t, ' : prices'] )


    ##-----  gen 1 at Pmin, gen 6 block 3 marginal @ $60  -----
    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 5'
    p2[L, :] = array([
        [100, 100, 100],
        [100,   0,   0],
        [100, 100,   0]
    ])
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1150, 100, [], [], mpopt)
    Qfudge =  zeros(p.shape)
    Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)

    t_is( cp[G[0], :], 65, 4, [t, ' : gen 1 price'] )
    t_is( cp[G[1], :], 57.1612, 4, [t, ' : gen 2 price'] )
    cq5 = cq.copy()
    cp5 = cp.copy()
    cp_lam = cp5.copy()
    cp_lam[0, :] = bus.lamP[Gbus[0]]  ## unclipped

    lao_X = p2[G[5], 2] / bus.lam_P[Gbus[5]]
    fro_X = p2[G[0], 2] / bus.lam_P[Gbus[0]]
    lab_X = p2[L[2], 1] / (bus.lam_P[Lbus[2]] + Qfudge[L[2], 0])
    frb_X = p2[L[1], 1] / (bus.lam_P[Lbus[1]] + Qfudge[L[1], 0])

    t_is( lao_X, 1, 4, 'lao_X')
    t_is( fro_X, 1.1425, 4, 'fro_X')
    t_is( lab_X, 1.5813, 4, 'lab_X')
    t_is( frb_X, 0, 4, 'frb_X')

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 1'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1110, 100, [], [], mpopt)
    cp1 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp5, 6, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 2'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1120, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp_lam * fro_X, 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 3'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1130, 100, [], [], mpopt)
    cp3 = cp.copy()
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp_lam * lab_X, 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 4'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1140, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, 0], [654042444660], 4, [t, ' : gen prices'] )
    t_is( cp[L, :], cp_lam[L, :] * frb_X, 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 6'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1160, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp_lam * fro_X, 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 7'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1170, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, cp_lam * (lao_X + lab_X) / 2, 8, [t, ' : prices'] )
    t_is( cp, (cp_lam + cp3) / 2, 7, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 8'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1180, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp[G, :], cp5[G, :], 7, [t, ' : prices'] )
    t_is( cp[L, :], cp3[L, :], 8, [t, ' : prices'] )

    t = 'gen 1 @ Pmin, marginal offer @ $60, auction_type = 0'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p2, 1100, 100, [], [], mpopt)
    t_is( cq, cq5, 8, [t, ' : quantities'] )
    t_is( cp, p2, 8, [t, ' : prices'] )


    ##-----  gen 2 decommitted, one offer block marginal @ $60  -----
    p[G[1], :] = p[G[1], :] + 100

    t = 'price of decommited gen, auction_type = 5'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1150, 200, [], [], mpopt)
    cp5 = cp.copy()
    Qfudge =  zeros(p.shape)
    Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
    t_is(sum(cq[1, :]), 0, 8, t)
    t_is(cp[1, 0], 59.194, 3, t)

    # Xo = p[0:6, :] / (diag(bus.lam_P[Gbus]) * ones(p[G, :].shape))
    # ao = (cq[0:6, :] != 0)
    # ro = (cq[0:6, :] == 0)
    # Xb = p[6:9, :] / (diag(bus.lam_P[Lbus] + gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape))
    # ab = (cq[6:9, :] != 0)
    # rb = (cq[6:9, :] == 0)
    # aXo = ao * Xo
    # rXo = ro * Xo
    # aXb = ab * Xb
    # rXb = rb * Xb

    lao_X = p[G[5], 2] / bus.lam_P[Gbus[5]]
    fro_X = p[G[0], 2] / bus.lam_P[Gbus[0]]
    lab_X = p[L[0], 1] / (bus.lam_P[Lbus[0]] + Qfudge[L[0], 0])
    frb_X = p[L[0], 2] / (bus.lam_P[Lbus[0]] + Qfudge[L[0], 0])

    t_is( lao_X, 1, 4, 'lao_X')
    t_is( fro_X, 1.0212, 4, 'fro_X')
    t_is( lab_X, 1.1649, 4, 'lab_X')
    t_is( frb_X, 0.9985, 4, 'frb_X')

    t = 'price of decommited gen, auction_type = 1'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1110, 200, [], [], mpopt)
    t_is(cp[1, 0], 59.194, 3, t)

    t = 'price of decommited gen, auction_type = 2'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1120, 200, [], [], mpopt)
    t_is(cp[1, 0], cp5[1, 0] * fro_X, 3, t)

    t = 'price of decommited gen, auction_type = 3'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1130, 200, [], [], mpopt)
    t_is(cp[1, 0], cp5[1, 0] * lab_X, 3, t)

    t = 'price of decommited gen, auction_type = 4'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1140, 200, [], [], mpopt)
    t_is(cp[1, 0], cp5[1, 0] * frb_X, 3, t)

    t = 'price of decommited gen, auction_type = 6'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1160, 200, [], [], mpopt)
    t_is(cp[1, 0], cp5[1, 0] * fro_X, 3, t)

    t = 'price of decommited gen, auction_type = 7'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1170, 200, [], [], mpopt)
    t_is(cp[1, 0], cp5[1, 0] * (lao_X + lab_X) / 2, 3, t)

    t = 'price of decommited gen, auction_type = 0'
    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1100, 200, [], [], mpopt)
    t_is(cp[1, 0], 120, 3, t)

    t = 'single block, marginal offer @ $50, auction_type = 5'
    q = array([
        [60],
        [36],
        [36],
        [36],
        [36],
        [36],
        [30],
        [10],
        [20]
    ])

    p = array([
        [50],
        [40],
        [42],
        [44],
        [46],
        [48],
        [100],
        [100],
        [100]
    ])

    MVAbase, cq, cp, bus, gen, gencost, branch, f, dispatch, success, et = \
        runmkt('t_auction_case', q, p, 1150, 100, [], [], mpopt)
    t_is( cq[G[0]], 35.32, 2, t )
    t_is( cq[G[1:6]], q[G[1:6]], 8, [t, ' : gen qtys'] )
    t_is( cp[G[0]], 50, 4, t )
    t_is( cq[L], q[L], 8, [t, ' : load qtys'] )
    t_is( cp[L[1], :], 54.03, 2, t )
    t_is( cp[G], bus.lam_P[Gbus], 8, [t, ' : gen prices'] )
    Qfudge =  zeros(p.shape)
    Qfudge[L, :] = diag(gen.Qg[L] / gen.Pg[L] * bus.lam_Q[Lbus]) * ones(p[L, :].shape)
    t_is( cp[L], bus.lam_P[Lbus] + Qfudge[L, 0], 8, [t, ' : load prices'] )

    t_end()
示例#57
0
def qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt):
    """Quadratic Program Solver based on GUROBI.

    A wrapper function providing a PYPOWER standardized interface for using
    gurobipy to solve the following QP (quadratic programming)
    problem:

        min 1/2 x'*H*x + c'*x
         x

    subject to

        l <= A*x <= u       (linear constraints)
        xmin <= x <= xmax   (variable bounds)

    Inputs (all optional except H, c, A and l):
        H : matrix (possibly sparse) of quadratic cost coefficients
        c : vector of linear cost coefficients
        A, l, u : define the optional linear constraints. Default
            values for the elements of l and u are -Inf and Inf,
            respectively.
        xmin, xmax : optional lower and upper bounds on the
            C{x} variables, defaults are -Inf and Inf, respectively.
        x0 : optional starting value of optimization vector C{x}
        opt : optional options structure with the following fields,
            all of which are also optional (default values shown in
            parentheses)
            verbose (0) - controls level of progress output displayed
                0 = no progress output
                1 = some progress output
                2 = verbose progress output
            grb_opt - options dict for Gurobi, value in
                verbose overrides these options
        problem : The inputs can alternatively be supplied in a single
            PROBLEM dict with fields corresponding to the input arguments
            described above: H, c, A, l, u, xmin, xmax, x0, opt

    Outputs:
        x : solution vector
        f : final objective function value
        exitflag : gurobipy exit flag
            1 = converged
            0 or negative values = negative of GUROBI_MEX exit flag
            (see gurobipy documentation for details)
        output : gurobipy output dict
            (see gurobipy documentation for details)
        lmbda : dict containing the Langrange and Kuhn-Tucker
            multipliers on the constraints, with fields:
            mu_l - lower (left-hand) limit on linear constraints
            mu_u - upper (right-hand) limit on linear constraints
            lower - lower bound on optimization variables
            upper - upper bound on optimization variables

    Note the calling syntax is almost identical to that of QUADPROG
    from MathWorks' Optimization Toolbox. The main difference is that
    the linear constraints are specified with A, l, u instead of
    A, b, Aeq, beq.

    Calling syntax options:
        x, f, exitflag, output, lmbda = ...
            qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt)

        r = qps_gurobi(H, c, A, l, u)
        r = qps_gurobi(H, c, A, l, u, xmin, xmax)
        r = qps_gurobi(H, c, A, l, u, xmin, xmax, x0)
        r = qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt)
        r = qps_gurobi(problem), where problem is a dict with fields:
                        H, c, A, l, u, xmin, xmax, x0, opt
                        all fields except 'c', 'A' and 'l' or 'u' are optional

    Example: (problem from from http://www.jmu.edu/docs/sasdoc/sashtml/iml/chap8/sect12.htm)
        H = [   1003.1  4.3     6.3     5.9;
                4.3     2.2     2.1     3.9;
                6.3     2.1     3.5     4.8;
                5.9     3.9     4.8     10  ]
        c = zeros((4, 1))
        A = [   [1       1       1       1]
                [0.17    0.11    0.10    0.18]    ]
        l = [1; 0.10]
        u = [1; Inf]
        xmin = zeros((4, 1))
        x0 = [1; 0; 0; 1]
        opt = {'verbose': 2}
        x, f, s, out, lmbda = qps_gurobi(H, c, A, l, u, xmin, [], x0, opt)

    @see: L{gurobipy}.
    """
    import gurobipy

    ##----- input argument handling  -----
    ## gather inputs
    if isinstance(H, dict):       ## problem struct
        p = H
        if 'opt' in p: opt = p['opt']
        if 'x0' in p: x0 = p['x0']
        if 'xmax' in p: xmax = p['xmax']
        if 'xmin' in p: xmin = p['xmin']
        if 'u' in p: u = p['u']
        if 'l' in p: l = p['l']
        if 'A' in p: A = p['A']
        if 'c' in p: c = p['c']
        if 'H' in p: H = p['H']
    else:                         ## individual args
        assert H is not None
        assert c is not None
        assert A is not None
        assert l is not None

    if opt is None:
        opt = {}
#    if x0 is None:
#        x0 = array([])
#    if xmax is None:
#        xmax = array([])
#    if xmin is None:
#        xmin = array([])

    ## define nx, set default values for missing optional inputs
    if len(H) == 0 or not any(any(H)):
        if len(A) == 0 and len(xmin) == 0 and len(xmax) == 0:
            stderr.write('qps_gurobi: LP problem must include constraints or variable bounds\n')
        else:
            if len(A) > 0:
                nx = shape(A)[1]
            elif len(xmin) > 0:
                nx = len(xmin)
            else:    # if len(xmax) > 0
                nx = len(xmax)
        H = sparse((nx, nx))
    else:
        nx = shape(H)[0]

    if len(c) == 0:
        c = zeros(nx)

    if  len(A) > 0 and (len(l) == 0 or all(l == -Inf)) and \
                       (len(u) == 0 or all(u ==  Inf)):
        A = None                    ## no limits => no linear constraints

    nA = shape(A)[0]                ## number of original linear constraints
    if nA:
        if len(u) == 0:             ## By default, linear inequalities are ...
            u = Inf * ones(nA)      ## ... unbounded above and ...

        if len(l) == 0:
            l = -Inf * ones(nA)     ## ... unbounded below.

    if len(x0) == 0:
        x0 = zeros(nx)

    ## default options
    if 'verbose' in opt:
        verbose = opt['verbose']
    else:
        verbose = 0

#    if 'max_it' in opt:
#        max_it = opt['max_it']
#    else:
#        max_it = 0

    ## set up options struct for Gurobi
    if 'grb_opt' in opt:
        g_opt = gurobi_options(opt['grb_opt'])
    else:
        g_opt = gurobi_options()

    g_opt['Display'] = min(verbose, 3)
    if verbose:
        g_opt['DisplayInterval'] = 1
    else:
        g_opt['DisplayInterval'] = Inf

    if not issparse(A):
        A = sparse(A)

    ## split up linear constraints
    ieq = find( abs(u-l) <= EPS )          ## equality
    igt = find( u >=  1e10 & l > -1e10 )   ## greater than, unbounded above
    ilt = find( l <= -1e10 & u <  1e10 )   ## less than, unbounded below
    ibx = find( (abs(u-l) > EPS) & (u < 1e10) & (l > -1e10) )

    ## grab some dimensions
    nlt = len(ilt)      ## number of upper bounded linear inequalities
    ngt = len(igt)      ## number of lower bounded linear inequalities
    nbx = len(ibx)      ## number of doubly bounded linear inequalities
    neq = len(ieq)      ## number of equalities
    niq = nlt + ngt + 2 * nbx    ## number of inequalities

    AA  = [ A[ieq, :], A[ilt, :], -A[igt, :], A[ibx, :], -A[ibx, :] ]
    bb  = [ u[ieq],    u[ilt],    -l[igt],    u[ibx],    -l[ibx]    ]
    contypes = '=' * neq + '<' * niq

    ## call the solver
    if len(H) == 0 or not any(any(H)):
        lpqp = 'LP'
    else:
        lpqp = 'QP'
        rr, cc, vv = find(H)
        g_opt['QP']['qrow'] = int(rr.T - 1)
        g_opt['QP']['qcol'] = int(cc.T - 1)
        g_opt['QP']['qval'] = 0.5 * vv.T

    if verbose:
        methods = [
            'primal simplex',
            'dual simplex',
            'interior point',
            'concurrent',
            'deterministic concurrent'
        ]
        print('Gurobi Version %s -- %s %s solver\n'
              '<unknown>' % (methods[g_opt['Method'] + 1], lpqp))

    x, f, eflag, output, lmbda = \
        gurobipy(c.T, 1, AA, bb, contypes, xmin, xmax, 'C', g_opt)
    pi  = lmbda['Pi']
    rc  = lmbda['RC']
    output['flag'] = eflag
    if eflag == 2:
        eflag = 1          ## optimal solution found
    else:
        eflag = -eflag     ## failed somehow

    ## check for empty results (in case optimization failed)
    lam = {}
    if len(x) == 0:
        x = NaN(nx, 1);
        lam['lower']   = NaN(nx)
        lam['upper']   = NaN(nx)
    else:
        lam['lower']   = zeros(nx)
        lam['upper']   = zeros(nx)

    if len(f) == 0:
        f = NaN

    if len(pi) == 0:
        pi  = NaN(len(bb))

    kl = find(rc > 0);   ## lower bound binding
    ku = find(rc < 0);   ## upper bound binding
    lam['lower'][kl]   =  rc[kl]
    lam['upper'][ku]   = -rc[ku]
    lam['eqlin']   = pi[:neq + 1]
    lam['ineqlin'] = pi[neq + range(niq + 1)]
    mu_l        = zeros(nA)
    mu_u        = zeros(nA)

    ## repackage lmbdas
    kl = find(lam['eqlin'] > 0)   ## lower bound binding
    ku = find(lam['eqlin'] < 0)   ## upper bound binding

    mu_l[ieq[kl]] = lam['eqlin'][kl]
    mu_l[igt] = -lam['ineqlin'][nlt + range(ngt + 1)]
    mu_l[ibx] = -lam['ineqlin'][nlt + ngt + nbx + range(nbx)]

    mu_u[ieq[ku]] = -lam['eqlin'][ku]
    mu_u[ilt] = -lam['ineqlin'][:nlt + 1]
    mu_u[ibx] = -lam['ineqlin'][nlt + ngt + range(nbx + 1)]

    lmbda = {
        'mu_l': mu_l,
        'mu_u': mu_u,
        'lower': lam['lower'],
        'upper': lam['upper']
    }

    return x, f, eflag, output, lmbda
def t_dcline(quiet=False):
    """Tests for DC line extension in L{{toggle_dcline}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    num_tests = 50

    t_begin(num_tests, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case9_dcline')
    if quiet:
        verbose = False
    else:
        verbose = False

    t0 = ''
    ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8,
            PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9)
    ppopt = ppoption(ppopt, OPF_ALG=560, OPF_ALG_DC=200)
    ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose)

    ## set up indices
    ib_data     = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)]
    ib_voltage  = arange(VM, VA + 1)
    ib_lam      = arange(LAM_P, LAM_Q + 1)
    ib_mu       = arange(MU_VMAX, MU_VMIN + 1)
    ig_data     = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)]
    ig_disp     = array([PG, QG, VG])
    ig_mu       = arange(MU_PMAX, MU_QMIN + 1)
    ibr_data    = arange(ANGMAX + 1)
    ibr_flow    = arange(PF, QT + 1)
    ibr_mu      = array([MU_SF, MU_ST])
    ibr_angmu   = array([MU_ANGMIN, MU_ANGMAX])

    ## load case
    ppc0 = loadcase(casefile)
    del ppc0['dclinecost']
    ppc = ppc0
    ppc = toggle_dcline(ppc, 'on')
    ppc = toggle_dcline(ppc, 'off')
    ndc = ppc['dcline'].shape[0]

    ## run AC OPF w/o DC lines
    t = ''.join([t0, 'AC OPF (no DC lines) : '])
    r0 = runopf(ppc0, ppopt)
    success = r0['success']
    t_ok(success, [t, 'success'])
    r = runopf(ppc, ppopt)
    success = r['success']
    t_ok(success, [t, 'success'])
    t_is(r['f'], r0['f'], 8, [t, 'f'])
    t_is(   r['bus'][:,ib_data   ],    r0['bus'][:,ib_data   ], 10, [t, 'bus data'])
    t_is(   r['bus'][:,ib_voltage],    r0['bus'][:,ib_voltage],  3, [t, 'bus voltage'])
    t_is(   r['bus'][:,ib_lam    ],    r0['bus'][:,ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   r['bus'][:,ib_mu     ],    r0['bus'][:,ib_mu     ],  2, [t, 'bus mu'])
    t_is(   r['gen'][:,ig_data   ],    r0['gen'][:,ig_data   ], 10, [t, 'gen data'])
    t_is(   r['gen'][:,ig_disp   ],    r0['gen'][:,ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   r['gen'][:,ig_mu     ],    r0['gen'][:,ig_mu     ],  3, [t, 'gen mu'])
    t_is(r['branch'][:,ibr_data  ], r0['branch'][:,ibr_data  ], 10, [t, 'branch data'])
    t_is(r['branch'][:,ibr_flow  ], r0['branch'][:,ibr_flow  ],  3, [t, 'branch flow'])
    t_is(r['branch'][:,ibr_mu    ], r0['branch'][:,ibr_mu    ],  2, [t, 'branch mu'])

    t = ''.join([t0, 'AC PF (no DC lines) : '])
    ppc1 = {'baseMVA': r['baseMVA'],
            'bus': r['bus'][:, :VMIN + 1].copy(),
            'gen': r['gen'][:, :APF + 1].copy(),
            'branch': r['branch'][:, :ANGMAX + 1].copy(),
            'gencost': r['gencost'].copy(),
            'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
    ppc1['bus'][:, VM] = 1
    ppc1['bus'][:, VA] = 0
    rp = runpf(ppc1, ppopt)
    success = rp['success']
    t_ok(success, [t, 'success'])
    t_is(   rp['bus'][:,ib_voltage],    r['bus'][:,ib_voltage],  3, [t, 'bus voltage'])
    t_is(   rp['gen'][:,ig_disp   ],    r['gen'][:,ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(rp['branch'][:,ibr_flow  ], r['branch'][:,ibr_flow  ],  3, [t, 'branch flow'])

    ## run with DC lines
    t = ''.join([t0, 'AC OPF (with DC lines) : '])
    ppc = toggle_dcline(ppc, 'on')
    r = runopf(ppc, ppopt)
    success = r['success']
    t_ok(success, [t, 'success'])
    expected = array([
        [10,     8.9,  -10,       10, 1.0674, 1.0935],
        [2.2776, 2.2776, 0,        0, 1.0818, 1.0665],
        [0,      0,      0,        0, 1.0000, 1.0000],
        [10,     9.5,    0.0563, -10, 1.0778, 1.0665]
    ])
    t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V'])
    expected = array([
        [0, 0.8490, 0.6165, 0,      0,      0.2938],
        [0, 0,      0,      0.4290, 0.0739, 0],
        [0, 0,      0,      0,      0,      0],
        [0, 7.2209, 0,      0,      0.0739, 0]
    ])
    t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu'])

    t = ''.join([t0, 'AC PF (with DC lines) : '])
    ppc1 = {'baseMVA': r['baseMVA'],
            'bus': r['bus'][:, :VMIN + 1].copy(),
            'gen': r['gen'][:, :APF + 1].copy(),
            'branch': r['branch'][:, :ANGMAX + 1].copy(),
            'gencost': r['gencost'].copy(),
            'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
    ppc1 = toggle_dcline(ppc1, 'on')
    ppc1['bus'][:, VM] = 1
    ppc1['bus'][:, VA] = 0
    rp = runpf(ppc1, ppopt)
    success = rp['success']
    t_ok(success, [t, 'success'])
    t_is(   rp['bus'][:,ib_voltage],    r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
    #t_is(   rp['gen'][:,ig_disp   ],    r['gen'][:,ig_disp   ], 3, [t, 'gen dispatch'])
    t_is(   rp['gen'][:2,ig_disp ],    r['gen'][:2,ig_disp ], 3, [t, 'gen dispatch'])
    t_is(   rp['gen'][2,PG        ],    r['gen'][2,PG        ], 3, [t, 'gen dispatch'])
    t_is(   rp['gen'][2,QG]+rp['dcline'][0,c.QF], r['gen'][2,QG]+r['dcline'][0,c.QF], 3, [t, 'gen dispatch'])
    t_is(rp['branch'][:,ibr_flow  ], r['branch'][:,ibr_flow  ], 3, [t, 'branch flow'])

    ## add appropriate P and Q injections and check angles and generation when running PF
    t = ''.join([t0, 'AC PF (with equivalent injections) : '])
    ppc1 = {'baseMVA': r['baseMVA'],
            'bus': r['bus'][:, :VMIN + 1].copy(),
            'gen': r['gen'][:, :APF + 1].copy(),
            'branch': r['branch'][:, :ANGMAX + 1].copy(),
            'gencost': r['gencost'].copy(),
            'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
    ppc1['bus'][:, VM] = 1
    ppc1['bus'][:, VA] = 0
    for k in range(ndc):
        if ppc1['dcline'][k, c.BR_STATUS]:
            ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS])
            tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS])
            ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF]
            ppc1['bus'][ff, QD] = ppc1['bus'][ff, QD] - r['dcline'][k, c.QF]
            ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT]
            ppc1['bus'][tt, QD] = ppc1['bus'][tt, QD] - r['dcline'][k, c.QT]
            ppc1['bus'][ff, VM] = r['dcline'][k, c.VF]
            ppc1['bus'][tt, VM] = r['dcline'][k, c.VT]
            ppc1['bus'][ff, BUS_TYPE] = PV
            ppc1['bus'][tt, BUS_TYPE] = PV

    rp = runpf(ppc1, ppopt)
    success = rp['success']
    t_ok(success, [t, 'success'])
    t_is(   rp['bus'][:,ib_voltage],    r['bus'][:,ib_voltage],  3, [t, 'bus voltage'])
    t_is(   rp['gen'][:,ig_disp   ],    r['gen'][:,ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(rp['branch'][:,ibr_flow  ], r['branch'][:,ibr_flow  ],  3, [t, 'branch flow'])

    ## test DC OPF
    t = ''.join([t0, 'DC OPF (with DC lines) : '])
    ppc = ppc0.copy()
    ppc['gen'][0, PMIN] = 10
    ppc['branch'][4, RATE_A] = 100
    ppc = toggle_dcline(ppc, 'on')
    r = rundcopf(ppc, ppopt)
    success = r['success']
    t_ok(success, [t, 'success'])
    expected = array([
        [10, 8.9, 0, 0, 1.01, 1],
        [2,  2,   0, 0, 1,    1],
        [0,  0,   0, 0, 1,    1],
        [10, 9.5, 0, 0, 1, 0.98]
    ])
    t_is(r['dcline'][:, c.PF:c.VT + 1], expected, 4, [t, 'P Q V'])
    expected = array([
        [0,      1.8602, 0, 0, 0, 0],
        [1.8507, 0,      0, 0, 0, 0],
        [0,      0,      0, 0, 0, 0],
        [0,      0.2681, 0, 0, 0, 0]
    ])
    t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected, 3, [t, 'mu'])

    t = ''.join([t0, 'DC PF (with DC lines) : '])
    ppc1 = {'baseMVA': r['baseMVA'],
            'bus': r['bus'][:, :VMIN + 1].copy(),
            'gen': r['gen'][:, :APF + 1].copy(),
            'branch': r['branch'][:, :ANGMAX + 1].copy(),
            'gencost': r['gencost'].copy(),
            'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
    ppc1 = toggle_dcline(ppc1, 'on')
    ppc1['bus'][:, VA] = 0
    rp = rundcpf(ppc1, ppopt)
    success = rp['success']
    t_ok(success, [t, 'success'])
    t_is(   rp['bus'][:,ib_voltage],    r['bus'][:,ib_voltage], 3, [t, 'bus voltage'])
    t_is(   rp['gen'][:,ig_disp   ],    r['gen'][:,ig_disp   ], 3, [t, 'gen dispatch'])
    t_is(rp['branch'][:,ibr_flow  ], r['branch'][:,ibr_flow  ], 3, [t, 'branch flow'])

    ## add appropriate P injections and check angles and generation when running PF
    t = ''.join([t0, 'DC PF (with equivalent injections) : '])
    ppc1 = {'baseMVA': r['baseMVA'],
            'bus': r['bus'][:, :VMIN + 1].copy(),
            'gen': r['gen'][:, :APF + 1].copy(),
            'branch': r['branch'][:, :ANGMAX + 1].copy(),
            'gencost': r['gencost'].copy(),
            'dcline': r['dcline'][:, :c.LOSS1 + 1].copy()}
    ppc1['bus'][:, VA] = 0
    for k in range(ndc):
        if ppc1['dcline'][k, c.BR_STATUS]:
            ff = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.F_BUS])
            tt = find(ppc1['bus'][:, BUS_I] == ppc1['dcline'][k, c.T_BUS])
            ppc1['bus'][ff, PD] = ppc1['bus'][ff, PD] + r['dcline'][k, c.PF]
            ppc1['bus'][tt, PD] = ppc1['bus'][tt, PD] - r['dcline'][k, c.PT]
            ppc1['bus'][ff, BUS_TYPE] = PV
            ppc1['bus'][tt, BUS_TYPE] = PV

    rp = rundcpf(ppc1, ppopt)
    success = rp['success']
    t_ok(success, [t, 'success'])
    t_is(   rp['bus'][:,ib_voltage],    r['bus'][:,ib_voltage],  3, [t, 'bus voltage'])
    t_is(   rp['gen'][:,ig_disp   ],    r['gen'][:,ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(rp['branch'][:,ibr_flow  ], r['branch'][:,ibr_flow  ],  3, [t, 'branch flow'])

    ## run with DC lines
    t = ''.join([t0, 'AC OPF (with DC lines + poly cost) : '])
    ppc = loadcase(casefile)
    ppc = toggle_dcline(ppc, 'on')
    r = runopf(ppc, ppopt)
    success = r['success']
    t_ok(success, [t, 'success'])
    expected1 = array([
        [10,     8.9,   -10,       10, 1.0663, 1.0936],
        [7.8429, 7.8429,  0,        0, 1.0809, 1.0667],
        [0,      0,       0,        0, 1.0000, 1.0000],
        [6.0549, 5.7522, -0.5897, -10, 1.0778, 1.0667]
    ])
    t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V'])
    expected2 = array([
        [0, 0.7605, 0.6226, 0,      0,      0.2980],
        [0, 0,      0,      0.4275, 0.0792, 0],
        [0, 0,      0,      0,      0,      0],
        [0, 0,      0,      0,      0.0792, 0]
    ])
    t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu'])

    ppc['dclinecost'][3, :8] = array([2, 0, 0, 4, 0, 0, 7.3, 0])
    r = runopf(ppc, ppopt)
    success = r['success']
    t_ok(success, [t, 'success'])
    t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V'])
    t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu'])

    t = ''.join([t0, 'AC OPF (with DC lines + pwl cost) : '])
    ppc['dclinecost'][3, :8] = array([1, 0, 0, 2, 0, 0, 10, 73])
    r = runopf(ppc, ppopt)
    success = r['success']
    t_ok(success, [t, 'success'])
    t_is(r['dcline'][:, c.PF:c.VT + 1], expected1, 4, [t, 'P Q V'])
    t_is(r['dcline'][:, c.MU_PMIN:c.MU_QMAXT + 1], expected2, 3, [t, 'mu'])

    t_end()
示例#59
0
def dcopf_solver(om, ppopt, out_opt=None):
    """Solves a DC optimal power flow.

    Inputs are an OPF model object, a PYPOWER options dict and
    a dict containing fields (can be empty) for each of the desired
    optional output fields.

    Outputs are a C{results} dict, C{success} flag and C{raw} output dict.

    C{results} is a PYPOWER case dict (ppc) with the usual baseMVA, bus
    branch, gen, gencost fields, along with the following additional
    fields:
        - C{order}      see 'help ext2int' for details of this field
        - C{x}          final value of optimization variables (internal order)
        - C{f}          final objective function value
        - C{mu}         shadow prices on ...
            - C{var}
                - C{l}  lower bounds on variables
                - C{u}  upper bounds on variables
            - C{lin}
                - C{l}  lower bounds on linear constraints
                - C{u}  upper bounds on linear constraints
        - C{g}          (optional) constraint values
        - C{dg}         (optional) constraint 1st derivatives
        - C{df}         (optional) obj fun 1st derivatives (not yet implemented)
        - C{d2f}        (optional) obj fun 2nd derivatives (not yet implemented)

    C{success} is C{True} if solver converged successfully, C{False} otherwise.

    C{raw} is a raw output dict in form returned by MINOS
        - C{xr}     final value of optimization variables
        - C{pimul}  constraint multipliers
        - C{info}   solver specific termination code
        - C{output} solver specific output information

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

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    """
    if out_opt is None:
        out_opt = {}

    ## options
    verbose = ppopt['VERBOSE']
    alg     = ppopt['OPF_ALG_DC']

    if alg == 0:
        if have_fcn('cplex'):        ## use CPLEX by default, if available
            alg = 500
        elif have_fcn('mosek'):      ## if not, then MOSEK, if available
            alg = 600
        elif have_fcn('gurobi'):     ## if not, then Gurobi, if available
            alg = 700
        else:                        ## otherwise PIPS
            alg = 200

    ## unpack data
    ppc = om.get_ppc()
    baseMVA, bus, gen, branch, gencost = \
        ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
    cp = om.get_cost_params()
    N, H, Cw = cp["N"], cp["H"], cp["Cw"]
    fparm = array(c_[cp["dd"], cp["rh"], cp["kk"], cp["mm"]])
    Bf = om.userdata('Bf')
    Pfinj = om.userdata('Pfinj')
    vv, ll, _, _ = om.get_idx()

    ## problem dimensions
    ipol = find(gencost[:, MODEL] == POLYNOMIAL) ## polynomial costs
    ipwl = find(gencost[:, MODEL] == PW_LINEAR)  ## piece-wise linear costs
    nb = bus.shape[0]              ## number of buses
    nl = branch.shape[0]           ## number of branches
    nw = N.shape[0]                ## number of general cost vars, w
    ny = om.getN('var', 'y')       ## number of piece-wise linear costs
    nxyz = om.getN('var')          ## total number of control vars of all types

    ## linear constraints & variable bounds
    A, l, u = om.linear_constraints()
    x0, xmin, xmax = om.getv()

    ## set up objective function of the form: f = 1/2 * X'*HH*X + CC'*X
    ## where X = [x;y;z]. First set up as quadratic function of w,
    ## f = 1/2 * w'*HHw*w + CCw'*w, where w = diag(M) * (N*X - Rhat). We
    ## will be building on the (optionally present) user supplied parameters.

    ## piece-wise linear costs
    any_pwl = int(ny > 0)
    if any_pwl:
        # Sum of y vars.
        Npwl = sparse((ones(ny), (zeros(ny), arange(vv["i1"]["y"], vv["iN"]["y"]))), (1, nxyz))
        Hpwl = sparse((1, 1))
        Cpwl = array([1])
        fparm_pwl = array([[1, 0, 0, 1]])
    else:
        Npwl = None#zeros((0, nxyz))
        Hpwl = None#array([])
        Cpwl = array([])
        fparm_pwl = zeros((0, 4))

    ## quadratic costs
    npol = len(ipol)
    if any(find(gencost[ipol, NCOST] > 3)):
        stderr.write('DC opf cannot handle polynomial costs with higher '
                     'than quadratic order.\n')
    iqdr = find(gencost[ipol, NCOST] == 3)
    ilin = find(gencost[ipol, NCOST] == 2)
    polycf = zeros((npol, 3))         ## quadratic coeffs for Pg
    if len(iqdr) > 0:
        polycf[iqdr, :] = gencost[ipol[iqdr], COST:COST + 3]
    if npol:
        polycf[ilin, 1:3] = gencost[ipol[ilin], COST:COST + 2]
    polycf = dot(polycf, diag([ baseMVA**2, baseMVA, 1]))     ## convert to p.u.
    if npol:
        Npol = sparse((ones(npol), (arange(npol), vv["i1"]["Pg"] + ipol)),
                      (npol, nxyz))  # Pg vars
        Hpol = sparse((2 * polycf[:, 0], (arange(npol), arange(npol))),
                      (npol, npol))
    else:
        Npol = None
        Hpol = None
    Cpol = polycf[:, 1]
    fparm_pol = ones((npol, 1)) * array([[1, 0, 0, 1]])

    ## combine with user costs
    NN = vstack([n for n in [Npwl, Npol, N] if n is not None and n.shape[0] > 0], "csr")
    # FIXME: Zero dimension sparse matrices.
    if (Hpwl is not None) and any_pwl and (npol + nw):
        Hpwl = hstack([Hpwl, sparse((any_pwl, npol + nw))])
    if Hpol is not None:
        if any_pwl and npol:
            Hpol = hstack([sparse((npol, any_pwl)), Hpol])
        if npol and nw:
            Hpol = hstack([Hpol, sparse((npol, nw))])
    if (H is not None) and nw and (any_pwl + npol):
        H = hstack([sparse((nw, any_pwl + npol)), H])
    HHw = vstack([h for h in [Hpwl, Hpol, H] if h is not None and h.shape[0] > 0], "csr")
    CCw = r_[Cpwl, Cpol, Cw]
    ffparm = r_[fparm_pwl, fparm_pol, fparm]

    ## transform quadratic coefficients for w into coefficients for X
    nnw = any_pwl + npol + nw
    M = sparse((ffparm[:, 3], (range(nnw), range(nnw))))
    MR = M * ffparm[:, 1]
    HMR = HHw * MR
    MN = M * NN
    HH = MN.T * HHw * MN
    CC = MN.T * (CCw - HMR)
    C0 = 0.5 * dot(MR, HMR) + sum(polycf[:, 2])  # Constant term of cost.

    ## set up input for QP solver
    opt = {'alg': alg, 'verbose': verbose}
    if (alg == 200) or (alg == 250):
        ## try to select an interior initial point
        Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180.0)

        lb, ub = xmin.copy(), xmax.copy()
        lb[xmin == -Inf] = -1e10   ## replace Inf with numerical proxies
        ub[xmax ==  Inf] =  1e10
        x0 = (lb + ub) / 2;
        # angles set to first reference angle
        x0[vv["i1"]["Va"]:vv["iN"]["Va"]] = Varefs[0]
        if ny > 0:
            ipwl = find(gencost[:, MODEL] == PW_LINEAR)
            # largest y-value in CCV data
            c = gencost.flatten('F')[sub2ind(gencost.shape, ipwl,
                                NCOST + 2 * gencost[ipwl, NCOST])]
            x0[vv["i1"]["y"]:vv["iN"]["y"]] = max(c) + 0.1 * abs(max(c))

        ## set up options
        feastol = ppopt['PDIPM_FEASTOL']
        gradtol = ppopt['PDIPM_GRADTOL']
        comptol = ppopt['PDIPM_COMPTOL']
        costtol = ppopt['PDIPM_COSTTOL']
        max_it  = ppopt['PDIPM_MAX_IT']
        max_red = ppopt['SCPDIPM_RED_IT']
        if feastol == 0:
            feastol = ppopt['OPF_VIOLATION']    ## = OPF_VIOLATION by default
        opt["pips_opt"] = {  'feastol': feastol,
                             'gradtol': gradtol,
                             'comptol': comptol,
                             'costtol': costtol,
                             'max_it':  max_it,
                             'max_red': max_red,
                             'cost_mult': 1  }
    elif alg == 400:
        opt['ipopt_opt'] = ipopt_options([], ppopt)
    elif alg == 500:
        opt['cplex_opt'] = cplex_options([], ppopt)
    elif alg == 600:
        opt['mosek_opt'] = mosek_options([], ppopt)
    elif alg == 700:
        opt['grb_opt'] = gurobi_options([], ppopt)
    else:
        raise ValueError("Unrecognised solver [%d]." % alg)

    ##-----  run opf  -----
    x, f, info, output, lmbda = \
            qps_pypower(HH, CC, A, l, u, xmin, xmax, x0, opt)
    success = (info == 1)

    ##-----  calculate return values  -----
    if not any(isnan(x)):
        ## update solution data
        Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
        Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]]
        f = f + C0

        ## update voltages & generator outputs
        bus[:, VA] = Va * 180 / pi
        gen[:, PG] = Pg * baseMVA

        ## compute branch flows
        branch[:, [QF, QT]] = zeros((nl, 2))
        branch[:, PF] = (Bf * Va + Pfinj) * baseMVA
        branch[:, PT] = -branch[:, PF]

    ## package up results
    mu_l = lmbda["mu_l"]
    mu_u = lmbda["mu_u"]
    muLB = lmbda["lower"]
    muUB = lmbda["upper"]

    ## update Lagrange multipliers
    il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
    bus[:, [LAM_P, LAM_Q, MU_VMIN, MU_VMAX]] = zeros((nb, 4))
    gen[:, [MU_PMIN, MU_PMAX, MU_QMIN, MU_QMAX]] = zeros((gen.shape[0], 4))
    branch[:, [MU_SF, MU_ST]] = zeros((nl, 2))
    bus[:, LAM_P]       = (mu_u[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]] -
                           mu_l[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]]) / baseMVA
    branch[il, MU_SF]   = mu_u[ll["i1"]["Pf"]:ll["iN"]["Pf"]] / baseMVA
    branch[il, MU_ST]   = mu_u[ll["i1"]["Pt"]:ll["iN"]["Pt"]] / baseMVA
    gen[:, MU_PMIN]     = muLB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
    gen[:, MU_PMAX]     = muUB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA

    pimul = r_[
      mu_l - mu_u,
     -ones(int(ny > 0)), ## dummy entry corresponding to linear cost row in A
      muLB - muUB
    ]

    mu = { 'var': {'l': muLB, 'u': muUB},
           'lin': {'l': mu_l, 'u': mu_u} }

    results = deepcopy(ppc)
    results["bus"], results["branch"], results["gen"], \
        results["om"], results["x"], results["mu"], results["f"] = \
            bus, branch, gen, om, x, mu, f

    raw = {'xr': x, 'pimul': pimul, 'info': info, 'output': output}

    return results, success, raw