Ejemplo n.º 1
0
def runopf_w_res(*args):
    """Runs an optimal power flow with fixed zonal reserves.

    Runs an optimal power flow with the addition of reserve requirements
    specified as a set of fixed zonal reserves. See L{runopf} for a
    description of the input and output arguments, which are the same,
    with the exception that the case file or dict C{casedata} must define
    a 'reserves' field, which is a dict with the following fields:
        - C{zones}   C{nrz x ng}, C{zone(i, j) = 1}, if gen C{j} belongs
        to zone C{i} 0, otherwise
        - C{req}     C{nrz x 1}, zonal reserve requirement in MW
        - C{cost}    (C{ng} or C{ngr}) C{x 1}, cost of reserves in $/MW
        - C{qty}     (C{ng} or C{ngr}) C{x 1}, max quantity of reserves
        in MW (optional)
    where C{nrz} is the number of reserve zones and C{ngr} is the number of
    generators belonging to at least one reserve zone and C{ng} is the total
    number of generators.

    In addition to the normal OPF output, the C{results} dict contains a
    new 'reserves' field with the following fields, in addition to those
    provided in the input:
        - C{R}       - C{ng x 1}, reserves provided by each gen in MW
        - C{Rmin}    - C{ng x 1}, lower limit on reserves provided by
        each gen, (MW)
        - C{Rmax}    - C{ng x 1}, upper limit on reserves provided by
        each gen, (MW)
        - C{mu.l}    - C{ng x 1}, shadow price on reserve lower limit, ($/MW)
        - C{mu.u}    - C{ng x 1}, shadow price on reserve upper limit, ($/MW)
        - C{mu.Pmax} - C{ng x 1}, shadow price on C{Pg + R <= Pmax}
        constraint, ($/MW)
        - C{prc}     - C{ng x 1}, reserve price for each gen equal to
        maximum of the shadow prices on the zonal requirement constraint
        for each zone the generator belongs to

    See L{t.t_case30_userfcns} for an example case file with fixed reserves,
    and L{toggle_reserves} for the implementation.

    Calling syntax options::
        results = runopf_w_res(casedata)
        results = runopf_w_res(casedata, ppopt)
        results = runopf_w_res(casedata, ppopt, fname)
        results = runopf_w_res(casedata, [popt, fname, solvedcase)
        results, success = runopf_w_res(...)

    Example::
        results = runopf_w_res('t_case30_userfcns')

    @see: L{runopf}, L{toggle_reserves}, L{t.t_case30_userfcns}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ppc = loadcase(args[0])
    ppc = toggle_reserves(ppc, 'on')

    r = runopf(ppc, *args[1:])
    r = toggle_reserves(r, 'off')

    return r
Ejemplo n.º 2
0
def runopf_w_res(*args):
    """Runs an optimal power flow with fixed zonal reserves.

    Runs an optimal power flow with the addition of reserve requirements
    specified as a set of fixed zonal reserves. See L{runopf} for a
    description of the input and output arguments, which are the same,
    with the exception that the case file or dict C{casedata} must define
    a 'reserves' field, which is a dict with the following fields:
        - C{zones}   C{nrz x ng}, C{zone(i, j) = 1}, if gen C{j} belongs
        to zone C{i} 0, otherwise
        - C{req}     C{nrz x 1}, zonal reserve requirement in MW
        - C{cost}    (C{ng} or C{ngr}) C{x 1}, cost of reserves in $/MW
        - C{qty}     (C{ng} or C{ngr}) C{x 1}, max quantity of reserves
        in MW (optional)
    where C{nrz} is the number of reserve zones and C{ngr} is the number of
    generators belonging to at least one reserve zone and C{ng} is the total
    number of generators.

    In addition to the normal OPF output, the C{results} dict contains a
    new 'reserves' field with the following fields, in addition to those
    provided in the input:
        - C{R}       - C{ng x 1}, reserves provided by each gen in MW
        - C{Rmin}    - C{ng x 1}, lower limit on reserves provided by
        each gen, (MW)
        - C{Rmax}    - C{ng x 1}, upper limit on reserves provided by
        each gen, (MW)
        - C{mu.l}    - C{ng x 1}, shadow price on reserve lower limit, ($/MW)
        - C{mu.u}    - C{ng x 1}, shadow price on reserve upper limit, ($/MW)
        - C{mu.Pmax} - C{ng x 1}, shadow price on C{Pg + R <= Pmax}
        constraint, ($/MW)
        - C{prc}     - C{ng x 1}, reserve price for each gen equal to
        maximum of the shadow prices on the zonal requirement constraint
        for each zone the generator belongs to

    See L{t.t_case30_userfcns} for an example case file with fixed reserves,
    and L{toggle_reserves} for the implementation.

    Calling syntax options::
        results = runopf_w_res(casedata)
        results = runopf_w_res(casedata, ppopt)
        results = runopf_w_res(casedata, ppopt, fname)
        results = runopf_w_res(casedata, [popt, fname, solvedcase)
        results, success = runopf_w_res(...)

    Example::
        results = runopf_w_res('t_case30_userfcns')

    @see: L{runopf}, L{toggle_reserves}, L{t.t_case30_userfcns}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ppc = loadcase(args[0])
    ppc = toggle_reserves(ppc, 'on')

    r = runopf(ppc, *args[1:])
    r = toggle_reserves(r, 'off')

    return r
def mc_simulation(eqstatus, Testsys, ppopt, Ng, Nl):
    statusgen = eqstatus[0:Ng]
    Testsys["gen"][0:Ng, 8] = 1 - statusgen
    statusbranch = eqstatus[Ng:Ng + Nl]
    Testsys["branch"][0:Nl, 10] = 1 - statusbranch

    Result = runopf(casedata=Testsys, ppopt=ppopt)
    dns = Result["f"] + Testsys["load"]
    if dns < 0.1:
        dns = 0
        return dns
Ejemplo n.º 4
0
def rundcopf(casedata=None, ppopt=None, fname='', solvedcase=''):
    """Runs a DC optimal power flow.

    @see: L{runopf}, L{runduopf}

    @author: Ray Zimmerman (PSERC Cornell)
    """
    ## default arguments
    if casedata is None:
        casedata = join(dirname(__file__), 'case9')
    ppopt = ppoption(ppopt, PF_DC=True)

    return runopf(casedata, ppopt, fname, solvedcase)
Ejemplo n.º 5
0
def rundcopf(casedata=None, ppopt=None, fname="", solvedcase=""):
    """Runs a DC optimal power flow.

    @see: L{runopf}, L{runduopf}

    @author: Ray Zimmerman (PSERC Cornell)
    """
    ## default arguments
    if casedata is None:
        casedata = join(dirname(__file__), "case9")
    ppopt = ppoption(ppopt, PF_DC=True)

    return runopf(casedata, ppopt, fname, solvedcase)
Ejemplo n.º 6
0
def mc_simulation(para):
    ppopt = para[2]
    Ng = para[3]
    Nl = para[4]
    statusgen = para[0][0:Ng]
    Testsys = para[1]
    Testsys["gen"][0:Ng, 7] = 1 - statusgen  # 此处已改
    statusbranch = para[0][Ng:Ng + Nl]
    Testsys["branch"][0:Nl, 10] = 1 - statusbranch
    Result = runopf(casedata=Testsys, ppopt=ppopt)
    dns = Result["f"] + Testsys["load"]
    if dns < 0.1:
        dns = 0
    return dns
Ejemplo n.º 7
0
    def run(self,
            Testsys=case24_ieee_rts(),
            BETAlimit=0.0017,
            ITER_max=10000,
            SIMUNIT=1000):
        Nb = Testsys["bus"].shape[0]  # Load test system,Nb为节点数,Ng为发电机组数,Nl为馈线数
        Ng = Testsys["gen"].shape[0]
        Nl = Testsys["branch"].shape[0]

        # Set initial value
        iter = 0
        betavalue = float('inf')  # The stopping criteria停止迭代的标准
        row_index = 0
        # Build matrices that have fix dimension to avoid changing size in each loop
        eqstatus_total = np.zeros(
            (ITER_max, Ng + Nl + 3))  # 建一个100000*(33+38+3)的矩阵
        beta_table = np.zeros((1, ITER_max // SIMUNIT))  # "//"除法得到的才是整数
        edns_table = np.zeros((1, ITER_max // SIMUNIT))  # 存放评价指标,大小为1*1000
        lole_table = np.zeros((1, ITER_max // SIMUNIT))
        plc_table = np.zeros((1, ITER_max // SIMUNIT))
        genbus = np.nonzero((Testsys["bus"][:, PD]))[
            0]  # 第三列(python中坐标是2)是节点的有功功率,表示节点有有功负荷,此处返回该列非零元素的索引,共有17个元素非零
        sizegenbus = genbus.shape[0]  # 有负荷的节点数量赋值给sizegenbus
        Testsys["load"] = sum(Testsys["bus"][:, PD])  # 系统需要的总有功功率
        Testsys["gencost"] = np.tile([2, 0, 0, 3, 0, 0, 0],
                                     (Ng, 1))  # np.tile建立重复矩阵块(设置机组费用)
        # treat all load as negtive generator and set their parameters, then add these vitual generators to real gens
        # 将所有载荷视为负发电机,并设置其参数,然后将这些发电机加到实际的发电机中
        loadcost = np.tile([2, 0, 0, 3, 0, 1, 0],
                           (sizegenbus, 1))  # np.tile建立重复矩阵块(负荷的“机组费用”)
        Testsys["gencost"] = np.append(Testsys["gencost"], loadcost, axis=0)
        Index = copy.deepcopy(Testsys["gen"][0:sizegenbus, :])  # 将前17台机组的数据取出
        Index[:, 0:10] = np.hstack(
            (Testsys["bus"][genbus, 0].reshape(-1, 1),
             -Testsys["bus"][genbus, 2].reshape(-1, 1),
             -Testsys["bus"][genbus, 3].reshape(-1, 1),
             np.zeros(
                 (sizegenbus, 1)), -Testsys["bus"][genbus, 3].reshape(-1, 1),
             np.zeros((sizegenbus, 1)), Testsys["baseMVA"] * np.ones(
                 (sizegenbus, 1)), np.ones((sizegenbus, 1)),
             np.zeros(
                 (sizegenbus, 1)), -Testsys["bus"][genbus, 2].reshape(-1, 1)))
        #  负荷参数代替取出的机组数据,将负荷套入机组模型,上面矩阵取数注意与matlab相比坐标要减一
        Testsys["gen"] = np.append(Testsys["gen"], Index, axis=0)
        del Index
        Testsys["bus"][genbus, 2:4] = 0  # 将原来节点中的第3、4列(有功、无功)负荷设为零
        totalprob = failprob()  # 引用前面定义的函数
        ppopt = ppoption(
            PF_DC=1, VERBOSE=0, OUT_ALL=0, OPF_ALG_DC=200, OPF_FLOW_LIM=1
        )  # 可以通过ppoption()采用默认变量来看里面需要什么样的输入,这个按照matlab来输入没问题吧?
        result = runopf(casedata=Testsys, ppopt=ppopt)
        while (betavalue > BETAlimit) & (iter < ITER_max):
            eqstatus_indi = mc_sampling(
                totalprob, SIMUNIT, Ng,
                Nl)  # eqstatus为元件的状态矩阵,为1表示元件故障,为0表示原件正常
            eqstatus_indi = np.hstack(
                (eqstatus_indi, np.ones((eqstatus_indi.shape[0], 1)),
                 np.zeros((eqstatus_indi.shape[0], 2))))
            # 在eqstatus_indi矩阵中加入三列,第一列代表状态重复次数,第二列记载切负荷量大小(没有切负荷则为零),第三列记载是否为容量不足
            eqstatus_indi, ia1 = np.unique(eqstatus_indi,
                                           axis=0,
                                           return_inverse=True)  # 找出抽样中的相同结果
            for i in range(eqstatus_indi.shape[0]):
                eqstatus_indi[i,
                              Ng + Nl] = sum(ia1 == i)  # 将重复记录次数在第Ng + Nl + 1
            if iter:
                x = 0
                y = eqstatus_indi.shape[0]
                for i in range(y):
                    indi_x = eqstatus_indi[x, 0:Ng + Nl]
                    for j in range(row_index):
                        if (indi_x == eqstatus_total[j, 0:Ng + Nl]).all():
                            eqstatus_total[j, Ng + Nl] = eqstatus_total[
                                j, Ng + Nl] + eqstatus_indi[
                                    x,
                                    Ng + Nl]  # 遇见相同的,就在eqstatus_total的计数中累加次数
                            eqstatus_indi = np.delete(eqstatus_indi, x, axis=0)
                            x = x - 1
                            break
                    x = x + 1
                parfortemp = np.zeros((eqstatus_indi.shape[0], 2))
                para = [0] * eqstatus_indi.shape[0]
                n_sample = [0] * eqstatus_indi.shape[0]
                for i in range(eqstatus_indi.shape[0]):
                    para[i] = [0] * 5
                    para[i][0] = eqstatus_indi[i, 0:Ng + Nl]
                    para[i][1] = Testsys
                    para[i][2] = ppopt
                    para[i][3] = Ng
                    para[i][4] = Nl
                with Pool(self.n_processors) as p:
                    load_shedding = list(p.map(mc_simulation, para))
                parfortemp[:, 0] = np.asarray(load_shedding)
                parfortemp[:, 1] = (parfortemp[:, 0]) != 0
                eqstatus_indi[:, Ng + Nl + 1:Ng + Nl + 3] = parfortemp
                eqstatus_total[row_index:row_index +
                               eqstatus_indi.shape[0], :] = eqstatus_indi
                row_index = row_index + eqstatus_indi.shape[0]
            else:
                parfortemp = np.zeros((eqstatus_indi.shape[0], 2))
                para = [0] * eqstatus_indi.shape[0]
                c = [0] * eqstatus_indi.shape[0]
                for i in range(eqstatus_indi.shape[0]):
                    para[i] = [0] * 5
                    para[i][0] = eqstatus_indi[i, 0:Ng + Nl]
                    para[i][1] = Testsys
                    para[i][2] = ppopt
                    para[i][3] = Ng
                    para[i][4] = Nl
                with Pool(self.n_processors) as p:
                    load_shedding = list(p.map(mc_simulation, para))  # 计算负荷短缺值
                parfortemp[:, 0] = np.asarray(load_shedding)
                parfortemp[:, 1] = (parfortemp[:, 0]) != 0  # 记录是否负荷短缺
                eqstatus_indi[:, Ng + Nl + 1:Ng + Nl + 3] = parfortemp
                eqstatus_total[row_index:row_index +
                               eqstatus_indi.shape[0], :] = eqstatus_indi
                row_index = row_index + eqstatus_indi.shape[0]
            ## Update index
            edns = sum(
                eqstatus_total[0:row_index, Ng + Nl] *
                eqstatus_total[0:row_index, Ng + Nl + 1]) / (iter + SIMUNIT)
            lole = sum(eqstatus_total[0:row_index, Ng + Nl] *
                       eqstatus_total[0:row_index, Ng + Nl + 2]) / (
                           iter + SIMUNIT) * 8760
            plc = sum(
                eqstatus_total[0:row_index, Ng + Nl] *
                eqstatus_total[0:row_index, Ng + Nl + 2]) / (iter + SIMUNIT)
            betavalue = (sum(eqstatus_total[0:row_index, Ng + Nl] *
                             (eqstatus_total[0:row_index, Ng + Nl + 1] - edns)
                             **2))**0.5 / (iter + SIMUNIT) / edns

            beta_table[0, ((iter + SIMUNIT) // SIMUNIT) - 1] = betavalue
            edns_table[0, ((iter + SIMUNIT) // SIMUNIT) - 1] = edns
            lole_table[0, ((iter + SIMUNIT) // SIMUNIT) - 1] = lole
            plc_table[0, ((iter + SIMUNIT) // SIMUNIT) - 1] = plc
            iter = iter + SIMUNIT
        return edns
Ejemplo n.º 8
0
        else:
            temp["PGMAX"] = 0
            temp["PGMIN"] = 0
            temp["QGMAX"] = 0
            temp["QGMIN"] = 0
            temp["a"] = 0
            temp["b"] = 0
            temp["c"] = 0
        temp["PD"] = bus[i, PD]
        temp["QD"] = bus[i, QD]
        temp["VMIN"] = bus[i, VMIN] ** 2
        temp["VMAX"] = bus[i, VMAX] ** 2

        Area.append(temp)

    return Area


if __name__ == "__main__":
    from pypower import runopf

    mpc = case33.case33()  # Default test case
    (obj, residual) = run(mpc)

    result = runopf.runopf(case33.case33())

    gap = 100 * (result["f"] - obj) / obj

    print(gap)
    print(residual)
Ejemplo n.º 9
0
def t_dcline(quiet=False):
    """Tests for DC line extension in L{{toggle_dcline}.

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

    t_begin(num_tests, quiet)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    t_end()
Ejemplo n.º 10
0
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()
def t_opf_ipopt(quiet=False):
    """Tests for IPOPT-based AC optimal power flow.

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

    t_begin(num_tests, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case9_opf')
    verbose = 0#not quiet

    t0 = 'IPOPT : '
    ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8,
                   PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9)
    ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=580)

    ## 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])

    ## get solved AC power flow case from MAT-file
    soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf['bus_soln']
    gen_soln = soln9_opf['gen_soln']
    branch_soln = soln9_opf['branch_soln']
    f_soln = soln9_opf['f_soln'][0]

    ## run OPF
    t = t0
    r = runopf(casefile, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    ## run with automatic conversion of single-block pwl to linear costs
    t = ''.join([t0, '(single-block PWL) : '])
    ppc = loadcase(casefile)
    ppc['gencost'][2, NCOST] = 2
    r = runopf(ppc, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    xr = r_[r['var']['val']['Va'], r['var']['val']['Vm'], r['var']['val']['Pg'],
            r['var']['val']['Qg'], 0, r['var']['val']['y']]
    t_is(r['x'], xr, 8, [t, 'check on raw x returned from OPF'])

    ## get solved AC power flow case from MAT-file
    soln9_opf_Plim = loadmat(join(tdir, 'soln9_opf_Plim.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_Plim['bus_soln']
    gen_soln = soln9_opf_Plim['gen_soln']
    branch_soln = soln9_opf_Plim['branch_soln']
    f_soln = soln9_opf_Plim['f_soln'][0]

    ## run OPF with active power line limits
    t = ''.join([t0, '(P line lim) : '])
    ppopt1 = ppoption(ppopt, OPF_FLOW_LIM=1)
    r = runopf(casefile, ppopt1)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    ##-----  test OPF with quadratic gen costs moved to generalized costs  -----
    ppc = loadcase(casefile)
    ppc['gencost'] = array([
        [2,   1500, 0,   3,   0.11,    5,   0],
        [2,   2000, 0,   3,   0.085,   1.2, 0],
        [2,   3000, 0,   3,   0.1225,  1,   0]
    ])
    r = runopf(ppc, ppopt)
    bus_soln, gen_soln, branch_soln, f_soln, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    branch_soln = branch_soln[:, :MU_ST + 1]

    A = None
    l = array([])
    u = array([])
    nb = ppc['bus'].shape[0]      # number of buses
    ng = ppc['gen'].shape[0]      # number of gens
    thbas = 0;                thend    = thbas + nb
    vbas     = thend;     vend     = vbas + nb
    pgbas    = vend;      pgend    = pgbas + ng
#    qgbas    = pgend;     qgend    = qgbas + ng
    nxyz = 2 * nb + 2 * ng
    N = sparse((ppc['baseMVA'] * ones(ng), (arange(ng), arange(pgbas, pgend))), (ng, nxyz))
    fparm = ones((ng, 1)) * array([[1, 0, 0, 1]])
    ix = argsort(ppc['gen'][:, 0])
    H = 2 * spdiags(ppc['gencost'][ix, 4], 0, ng, ng, 'csr')
    Cw = ppc['gencost'][ix, 5]
    ppc['gencost'][:, 4:7] = 0

    ## run OPF with quadratic gen costs moved to generalized costs
    t = ''.join([t0, 'w/quadratic generalized gen cost : '])
    r = opf(ppc, A, l, u, ppopt, N, fparm, H, Cw)
    f, bus, gen, branch, success = \
            r['f'], r['bus'], r['gen'], r['branch'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    t_is(r['cost']['usr'], f, 12, [t, 'user cost'])

    ##-----  run OPF with extra linear user constraints & costs  -----
    ## single new z variable constrained to be greater than or equal to
    ## deviation from 1 pu voltage at bus 1, linear cost on this z
    ## get solved AC power flow case from MAT-file
    soln9_opf_extras1 = loadmat(join(tdir, 'soln9_opf_extras1.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_extras1['bus_soln']
    gen_soln = soln9_opf_extras1['gen_soln']
    branch_soln = soln9_opf_extras1['branch_soln']
    f_soln = soln9_opf_extras1['f_soln'][0]

    row = [0, 0, 1, 1]
    col = [9, 24, 9, 24]
    A = sparse(([-1, 1, 1, 1], (row, col)), (2, 25))
    u = array([Inf, Inf])
    l = array([-1, 1])

    N = sparse(([1], ([0], [24])), (1, 25))    ## new z variable only
    fparm = array([[1, 0, 0, 1]])              ## w = r = z
    H = sparse((1, 1))                ## no quadratic term
    Cw = array([100.0])

    t = ''.join([t0, 'w/extra constraints & costs 1 : '])
    r = opf(casefile, A, l, u, ppopt, N, fparm, H, Cw)
    f, bus, gen, branch, success = \
            r['f'], r['bus'], r['gen'], r['branch'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    t_is(r['var']['val']['z'], 0.025419, 6, [t, 'user variable'])
    t_is(r['cost']['usr'], 2.5419, 4, [t, 'user cost'])

    ##-----  test OPF with capability curves  -----
    ppc = loadcase(join(tdir, 't_case9_opfv2'))
    ## remove angle diff limits
    ppc['branch'][0, ANGMAX] =  360
    ppc['branch'][8, ANGMIN] = -360

    ## get solved AC power flow case from MAT-file
    soln9_opf_PQcap = loadmat(join(tdir, 'soln9_opf_PQcap.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_PQcap['bus_soln']
    gen_soln = soln9_opf_PQcap['gen_soln']
    branch_soln = soln9_opf_PQcap['branch_soln']
    f_soln = soln9_opf_PQcap['f_soln'][0]

    ## run OPF with capability curves
    t = ''.join([t0, 'w/capability curves : '])
    r = runopf(ppc, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    ##-----  test OPF with angle difference limits  -----
    ppc = loadcase(join(tdir, 't_case9_opfv2'))
    ## remove capability curves
    ppc['gen'][ix_(arange(1, 3),
                   [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX])] = zeros((2, 6))

    ## get solved AC power flow case from MAT-file
    soln9_opf_ang = loadmat(join(tdir, 'soln9_opf_ang.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_ang['bus_soln']
    gen_soln = soln9_opf_ang['gen_soln']
    branch_soln = soln9_opf_ang['branch_soln']
    f_soln = soln9_opf_ang['f_soln'][0]

    ## run OPF with angle difference limits
    t = ''.join([t0, 'w/angle difference limits : '])
    r = runopf(ppc, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  1, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    t_is(branch[:, ibr_angmu ], branch_soln[:, ibr_angmu ],  2, [t, 'branch angle mu'])

    ##-----  test OPF with ignored angle difference limits  -----
    ## get solved AC power flow case from MAT-file
    soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf['bus_soln']
    gen_soln = soln9_opf['gen_soln']
    branch_soln = soln9_opf['branch_soln']
    f_soln = soln9_opf['f_soln'][0]

    ## run OPF with ignored angle difference limits
    t = ''.join([t0, 'w/ignored angle difference limits : '])
    ppopt1 = ppoption(ppopt, OPF_IGNORE_ANG_LIM=1)
    r = runopf(ppc, ppopt1)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    ## ang limits are not in this solution data, so let's remove them
    branch[0, ANGMAX] =  360
    branch[8, ANGMIN] = -360
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    t_end()
def t_opf_userfcns(quiet=False):
    """Tests for userfcn callbacks (reserves/iflims) w/OPF.

    Includes high-level tests of reserves and iflims implementations.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    t_begin(38, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case30_userfcns')
    verbose = 0#not quiet

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

    ## run the OPF with fixed reserves
    t = 'fixed reserves : '
    ppc = loadcase(casefile)
    ppc = toggle_reserves(ppc, 'on')
    r = runopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4, [t, 'reserves.R'])
    t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc'])
    t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4, [t, 'reserves.mu.Pmax'])
    t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l'])
    t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4, [t, 'reserves.mu.u'])
    t_ok('P' not in r['if'], [t, 'no iflims'])
    t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost'])

    t = 'toggle_reserves(ppc, \'off\') : ';
    ppc = toggle_reserves(ppc, 'off')
    r = runopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])
    t_ok('P' not in r['if'], [t, 'no iflims'])

    t = 'interface flow lims (DC) : '
    ppc = loadcase(casefile)
    ppc = toggle_iflims(ppc, 'on')
    r = rundcopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u'])
    t_is(r['branch'][13, PF], 8.244, 3, [t, 'flow in branch 14'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])

    t = 'reserves + interface flow lims (DC) : '
    ppc = loadcase(casefile)
    ppc = toggle_reserves(ppc, 'on')
    ppc = toggle_iflims(ppc, 'on')
    r = rundcopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 38.2573], 4, [t, 'if.mu.u'])
    t_is(r['reserves']['R'], [25, 15, 0, 0, 16.9, 3.1], 4, [t, 'reserves.R'])
    t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc'])
    t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4, [t, 'reserves.mu.Pmax'])
    t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l'])
    t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4, [t, 'reserves.mu.u'])
    t_is(r['reserves']['totalcost'], 179.05, 4, [t, 'totalcost'])

    t = 'interface flow lims (AC) : '
    ppc = toggle_reserves(ppc, 'off')
    r = runopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-9.101, 21.432], 3, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [0, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 10.198], 3, [t, 'if.mu.u'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])

    t = 'interface flow lims (line out) : '
    ppc = loadcase(casefile)
    ppc = toggle_iflims(ppc, 'on')
    ppc['branch'][11, BR_STATUS] = 0      ## take out line 6-10
    r = rundcopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u'])
    t_is(r['branch'][13, PF], 10.814, 3, [t, 'flow in branch 14'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])

    # r['reserves']['R']
    # r['reserves']['prc']
    # r['reserves']['mu.Pmax']
    # r['reserves']['mu']['l']
    # r['reserves']['mu']['u']
    # r['reserves']['totalcost']
    #
    # r['if']['P']
    # r['if']['mu']['l']
    # r['if']['mu']['u']

    t_end()
Ejemplo n.º 13
0
def t_opf_userfcns(quiet=False):
    """Tests for userfcn callbacks (reserves/iflims) w/OPF.

    Includes high-level tests of reserves and iflims implementations.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    t_begin(38, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case30_userfcns')
    verbose = 0  #not quiet

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

    ## run the OPF with fixed reserves
    t = 'fixed reserves : '
    ppc = loadcase(casefile)
    ppc = toggle_reserves(ppc, 'on')
    r = runopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['reserves']['R'], [25, 15, 0, 0, 19.3906, 0.6094], 4,
         [t, 'reserves.R'])
    t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc'])
    t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4,
         [t, 'reserves.mu.Pmax'])
    t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l'])
    t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4,
         [t, 'reserves.mu.u'])
    t_ok('P' not in r['if'], [t, 'no iflims'])
    t_is(r['reserves']['totalcost'], 177.8047, 4, [t, 'totalcost'])

    t = 'toggle_reserves(ppc, \'off\') : '
    ppc = toggle_reserves(ppc, 'off')
    r = runopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])
    t_ok('P' not in r['if'], [t, 'no iflims'])

    t = 'interface flow lims (DC) : '
    ppc = loadcase(casefile)
    ppc = toggle_iflims(ppc, 'on')
    r = rundcopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u'])
    t_is(r['branch'][13, PF], 8.244, 3, [t, 'flow in branch 14'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])

    t = 'reserves + interface flow lims (DC) : '
    ppc = loadcase(casefile)
    ppc = toggle_reserves(ppc, 'on')
    ppc = toggle_iflims(ppc, 'on')
    r = rundcopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 38.2573], 4, [t, 'if.mu.u'])
    t_is(r['reserves']['R'], [25, 15, 0, 0, 16.9, 3.1], 4, [t, 'reserves.R'])
    t_is(r['reserves']['prc'], [2, 2, 2, 2, 5.5, 5.5], 4, [t, 'reserves.prc'])
    t_is(r['reserves']['mu']['Pmax'], [0, 0, 0, 0, 0.5, 0], 4,
         [t, 'reserves.mu.Pmax'])
    t_is(r['reserves']['mu']['l'], [0, 0, 1, 2, 0, 0], 4, [t, 'reserves.mu.l'])
    t_is(r['reserves']['mu']['u'], [0.1, 0, 0, 0, 0, 0], 4,
         [t, 'reserves.mu.u'])
    t_is(r['reserves']['totalcost'], 179.05, 4, [t, 'totalcost'])

    t = 'interface flow lims (AC) : '
    ppc = toggle_reserves(ppc, 'off')
    r = runopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-9.101, 21.432], 3, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [0, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 10.198], 3, [t, 'if.mu.u'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])

    t = 'interface flow lims (line out) : '
    ppc = loadcase(casefile)
    ppc = toggle_iflims(ppc, 'on')
    ppc['branch'][11, BR_STATUS] = 0  ## take out line 6-10
    r = rundcopf(ppc, ppopt)
    t_ok(r['success'], [t, 'success'])
    t_is(r['if']['P'], [-15, 20], 4, [t, 'if.P'])
    t_is(r['if']['mu']['l'], [4.8427, 0], 4, [t, 'if.mu.l'])
    t_is(r['if']['mu']['u'], [0, 13.2573], 4, [t, 'if.mu.u'])
    t_is(r['branch'][13, PF], 10.814, 3, [t, 'flow in branch 14'])
    t_ok('R' not in r['reserves'], [t, 'no reserves'])

    # r['reserves']['R']
    # r['reserves']['prc']
    # r['reserves']['mu.Pmax']
    # r['reserves']['mu']['l']
    # r['reserves']['mu']['u']
    # r['reserves']['totalcost']
    #
    # r['if']['P']
    # r['if']['mu']['l']
    # r['if']['mu']['u']

    t_end()
Ejemplo n.º 14
0
def validate_from_ppc(
        ppc_net,
        net,
        pf_type="runpp",
        max_diff_values={
            "bus_vm_pu": 1e-6,
            "bus_va_degree": 1e-5,
            "branch_p_mw": 1e-6,
            "branch_q_mvar": 1e-6,
            "gen_p_mw": 1e-6,
            "gen_q_mvar": 1e-6
        },
        run=True):
    """
    This function validates the pypower case files to pandapower net structure conversion via a \
    comparison of loadflow calculation results. (Hence the opf cost conversion is not validated.)

    INPUT:

        **ppc_net** - The pypower case file, which must already contain the pypower powerflow
            results or pypower must be importable.

        **net** - The pandapower network.

    OPTIONAL:

        **pf_type** ("runpp", string) - Type of validated power flow. Possible are ("runpp",
            "rundcpp", "runopp", "rundcopp")

        **max_diff_values** - Dict of maximal allowed difference values. The keys must be
        'vm_pu', 'va_degree', 'p_branch_mw', 'q_branch_mvar', 'p_gen_mw' and 'q_gen_mvar' and
        the values floats.

        **run** (True, bool or list of two bools) - changing the value to False avoids trying to run
            (optimal) loadflows. Giving a list of two bools addresses first pypower and second
            pandapower.

    OUTPUT:

        **conversion_success** - conversion_success is returned as False if pypower or pandapower
        cannot calculate a powerflow or if the maximum difference values (max_diff_values )
        cannot be hold.

    EXAMPLE:

        import pandapower.converter as pc

        net = cv.from_ppc(ppc_net, f_hz=50)

        conversion_success = cv.validate_from_ppc(ppc_net, net)

    NOTE:

        The user has to take care that the loadflow results already are included in the provided \
        ppc_net or pypower is importable.
    """
    # check in case of optimal powerflow comparison whether cost information exist
    if "opp" in pf_type:
        if not (len(net.polynomial_cost) | len(net.piecewise_linear_cost)):
            if "gencost" in ppc_net:
                if not len(ppc_net["gencost"]):
                    logger.debug(
                        'ppc and pandapower net do not include cost information.'
                    )
                    return True
                else:
                    logger.error(
                        'The pandapower net does not include cost information.'
                    )
                    return False
            else:
                logger.debug(
                    'ppc and pandapower net do not include cost information.')
                return True

    # guarantee run parameter as list, for pypower and pandapower (optimal) powerflow run
    run = [run, run] if isinstance(run, bool) else run

    # --- check pypower powerflow success, if possible
    if pypower_import and run[0]:
        try:
            if pf_type == "runpp":
                ppc_net = runpf.runpf(ppc_net, ppopt)[0]
            elif pf_type == "rundcpp":
                ppc_net = rundcpf.rundcpf(ppc_net, ppopt)[0]
            elif pf_type == "runopp":
                ppc_net = runopf.runopf(ppc_net, ppopt)
            elif pf_type == "rundcopp":
                ppc_net = rundcopf.rundcopf(ppc_net, ppopt)
            else:
                raise ValueError("The pf_type %s is unknown" % pf_type)
        except:
            logger.debug("The pypower run did not work.")
    ppc_success = True
    if 'success' in ppc_net.keys():
        if ppc_net['success'] != 1:
            ppc_success = False
            logger.error(
                "The given ppc data indicates an unsuccessful pypower powerflow: "
                + "'ppc_net['success'] != 1'")
    if (ppc_net['branch'].shape[1] < 17):
        ppc_success = False
        logger.error(
            "The shape of given ppc data indicates missing pypower powerflow results."
        )

    # --- try to run a pandapower powerflow
    if run[1]:
        if pf_type == "runpp":
            try:
                pp.runpp(net,
                         init="dc",
                         calculate_voltage_angles=True,
                         trafo_model="pi")
            except pp.LoadflowNotConverged:
                try:
                    pp.runpp(net,
                             calculate_voltage_angles=True,
                             init="flat",
                             trafo_model="pi")
                except pp.LoadflowNotConverged:
                    try:
                        pp.runpp(net,
                                 trafo_model="pi",
                                 calculate_voltage_angles=False)
                        if "bus_va_degree" in max_diff_values.keys():
                            max_diff_values[
                                "bus_va_degree"] = 1e2 if max_diff_values[
                                    "bus_va_degree"] < 1e2 else max_diff_values[
                                        "bus_va_degree"]
                        logger.info("voltage_angles could be calculated.")
                    except pp.LoadflowNotConverged:
                        logger.error(
                            'The pandapower powerflow does not converge.')
        elif pf_type == "rundcpp":
            try:
                pp.rundcpp(net, trafo_model="pi")
            except pp.LoadflowNotConverged:
                logger.error('The pandapower dc powerflow does not converge.')
        elif pf_type == "runopp":
            try:
                pp.runopp(net, init="flat", calculate_voltage_angles=True)
            except pp.OPFNotConverged:
                try:
                    pp.runopp(net, init="pf", calculate_voltage_angles=True)
                except (pp.OPFNotConverged, pp.LoadflowNotConverged, KeyError):
                    try:
                        pp.runopp(net,
                                  init="flat",
                                  calculate_voltage_angles=False)
                        logger.info("voltage_angles could be calculated.")
                        if "bus_va_degree" in max_diff_values.keys():
                            max_diff_values[
                                "bus_va_degree"] = 1e2 if max_diff_values[
                                    "bus_va_degree"] < 1e2 else max_diff_values[
                                        "bus_va_degree"]
                    except pp.OPFNotConverged:
                        try:
                            pp.runopp(net,
                                      init="pf",
                                      calculate_voltage_angles=False)
                            if "bus_va_degree" in max_diff_values.keys():
                                max_diff_values[
                                    "bus_va_degree"] = 1e2 if max_diff_values[
                                        "bus_va_degree"] < 1e2 else max_diff_values[
                                            "bus_va_degree"]
                            logger.info("voltage_angles could be calculated.")
                        except (pp.OPFNotConverged, pp.LoadflowNotConverged,
                                KeyError):
                            logger.error(
                                'The pandapower optimal powerflow does not converge.'
                            )
        elif pf_type == "rundcopp":
            try:
                pp.rundcopp(net)
            except pp.LoadflowNotConverged:
                logger.error(
                    'The pandapower dc optimal powerflow does not converge.')
        else:
            raise ValueError("The pf_type %s is unknown" % pf_type)

    # --- prepare powerflow result comparison by reordering pp results as they are in ppc results
    if not ppc_success:
        return False
    if "opp" in pf_type:
        if not net.OPF_converged:
            return
    elif not net.converged:
        return False

    # --- store pypower powerflow results
    ppc_res = dict.fromkeys(ppc_elms)
    ppc_res["branch"] = ppc_net['branch'][:, 13:17]
    ppc_res["bus"] = ppc_net['bus'][:, 7:9]
    ppc_res["gen"] = ppc_net['gen'][:, 1:3]

    # --- pandapower bus result table
    pp_res = dict.fromkeys(ppc_elms)
    pp_res["bus"] = array(net.res_bus.sort_index()[['vm_pu', 'va_degree']])

    # --- pandapower gen result table
    pp_res["gen"] = zeros([1, 2])
    # consideration of parallel generators via storing how much generators have been considered
    # each node
    # if in ppc is only one gen -> numpy initially uses one dim array -> change to two dim array
    if len(ppc_net["gen"].shape) == 1:
        ppc_net["gen"] = array(ppc_net["gen"], ndmin=2)
    GENS = DataFrame(ppc_net['gen'][:, [0]].astype(int))
    GEN_uniq = GENS.drop_duplicates()
    already_used_gen = Series(zeros(GEN_uniq.shape[0]).astype(int),
                              index=[int(v) for v in GEN_uniq.values])
    change_q_compare = []
    for i, j in GENS.iterrows():
        current_bus_type, current_bus_idx, same_bus_gen_idx, first_same_bus_in_service_gen_idx, \
            last_same_bus_in_service_gen_idx = _gen_bus_info(ppc_net, i)
        if current_bus_type == 3 and i == first_same_bus_in_service_gen_idx:
            pp_res["gen"] = append(
                pp_res["gen"],
                array(net.res_ext_grid[net.ext_grid.bus == current_bus_idx][[
                    'p_mw', 'q_mvar'
                ]]).reshape((1, 2)), 0)
        elif current_bus_type == 2 and i == first_same_bus_in_service_gen_idx:
            pp_res["gen"] = append(
                pp_res["gen"],
                array(net.res_gen[net.gen.bus == current_bus_idx][[
                    'p_mw', 'q_mvar'
                ]]).reshape((1, 2)), 0)
        else:
            pp_res["gen"] = append(
                pp_res["gen"],
                array(net.res_sgen[net.sgen.bus == current_bus_idx][[
                    'p_mw', 'q_mvar'
                ]])[already_used_gen.at[int(j)]].reshape((1, 2)), 0)
            already_used_gen.at[int(j)] += 1
            change_q_compare += [int(j)]
    pp_res["gen"] = pp_res["gen"][1:, :]  # delete initial zero row

    # --- pandapower branch result table
    pp_res["branch"] = zeros([1, 4])
    # consideration of parallel branches via storing how often branches were considered
    # each node-to-node-connection
    try:
        init1 = concat([net.line.from_bus, net.line.to_bus], axis=1,
                       sort=True).drop_duplicates()
        init2 = concat([net.trafo.hv_bus, net.trafo.lv_bus], axis=1,
                       sort=True).drop_duplicates()
    except TypeError:
        # legacy pandas < 0.21
        init1 = concat([net.line.from_bus, net.line.to_bus],
                       axis=1).drop_duplicates()
        init2 = concat([net.trafo.hv_bus, net.trafo.lv_bus],
                       axis=1).drop_duplicates()
    init1['hv_bus'] = nan
    init1['lv_bus'] = nan
    init2['from_bus'] = nan
    init2['to_bus'] = nan
    try:
        already_used_branches = concat([init1, init2], axis=0, sort=True)
    except TypeError:
        # pandas < 0.21 legacy
        already_used_branches = concat([init1, init2], axis=0)
    already_used_branches['number'] = zeros(
        [already_used_branches.shape[0], 1]).astype(int)
    BRANCHES = DataFrame(ppc_net['branch'][:, [0, 1, 8, 9]])
    for i in BRANCHES.index:
        from_bus = pp.get_element_index(net,
                                        'bus',
                                        name=int(ppc_net['branch'][i, 0]))
        to_bus = pp.get_element_index(net,
                                      'bus',
                                      name=int(ppc_net['branch'][i, 1]))
        from_vn_kv = ppc_net['bus'][from_bus, 9]
        to_vn_kv = ppc_net['bus'][to_bus, 9]
        ratio = BRANCHES[2].at[i]
        angle = BRANCHES[3].at[i]
        # from line results
        if (from_vn_kv == to_vn_kv) & ((ratio == 0) |
                                       (ratio == 1)) & (angle == 0):
            pp_res["branch"] = append(
                pp_res["branch"],
                array(net.res_line[(net.line.from_bus == from_bus)
                                   & (net.line.to_bus == to_bus)][[
                                       'p_from_mw', 'q_from_mvar', 'p_to_mw',
                                       'q_to_mvar'
                                   ]])
                [int(already_used_branches.number.loc[
                    (already_used_branches.from_bus == from_bus) &
                    (already_used_branches.to_bus == to_bus)].values)].reshape(
                        1, 4), 0)
            already_used_branches.number.loc[
                (already_used_branches.from_bus == from_bus)
                & (already_used_branches.to_bus == to_bus)] += 1
        # from trafo results
        else:
            if from_vn_kv >= to_vn_kv:
                pp_res["branch"] = append(
                    pp_res["branch"],
                    array(net.res_trafo[(net.trafo.hv_bus == from_bus)
                                        & (net.trafo.lv_bus == to_bus)]
                          [['p_hv_mw', 'q_hv_mvar', 'p_lv_mw', 'q_lv_mvar'
                            ]])[int(already_used_branches.number.loc[
                                (already_used_branches.hv_bus == from_bus)
                                & (already_used_branches.lv_bus == to_bus)].
                                    values)].reshape(1, 4), 0)
                already_used_branches.number.loc[
                    (already_used_branches.hv_bus == from_bus)
                    & (already_used_branches.lv_bus == to_bus)] += 1
            else:  # switch hv-lv-connection of pypower connection buses
                pp_res["branch"] = append(
                    pp_res["branch"],
                    array(net.res_trafo[(net.trafo.hv_bus == to_bus)
                                        & (net.trafo.lv_bus == from_bus)]
                          [['p_lv_mw', 'q_lv_mvar', 'p_hv_mw', 'q_hv_mvar'
                            ]])[int(already_used_branches.number.loc[
                                (already_used_branches.hv_bus == to_bus)
                                & (already_used_branches.lv_bus == from_bus)].
                                    values)].reshape(1, 4), 0)
                already_used_branches.number.loc[
                    (already_used_branches.hv_bus == to_bus)
                    & (already_used_branches.lv_bus == from_bus)] += 1
    pp_res["branch"] = pp_res["branch"][1:, :]  # delete initial zero row

    # --- do the powerflow result comparison
    diff_res = dict.fromkeys(ppc_elms)
    diff_res["bus"] = ppc_res["bus"] - pp_res["bus"]
    diff_res["bus"][:, 1] -= diff_res["bus"][0, 1]  # remove va_degree offset
    diff_res["branch"] = ppc_res["branch"] - pp_res["branch"]
    diff_res["gen"] = ppc_res["gen"] - pp_res["gen"]
    # comparison of buses with several generator units only as q sum
    for i in GEN_uniq.loc[GEN_uniq[0].isin(change_q_compare)].index:
        next_is = GEN_uniq.index[GEN_uniq.index > i]
        if len(next_is) > 0:
            next_i = next_is[0]
        else:
            next_i = GENS.index[-1] + 1
        if (next_i - i) > 1:
            diff_res["gen"][i:next_i, 1] = sum(diff_res["gen"][i:next_i, 1])
    # logger info
    logger.debug(
        "Maximum voltage magnitude difference between pypower and pandapower: "
        "%.2e pu" % max_(abs(diff_res["bus"][:, 0])))
    logger.debug(
        "Maximum voltage angle difference between pypower and pandapower: "
        "%.2e degree" % max_(abs(diff_res["bus"][:, 1])))
    logger.debug(
        "Maximum branch flow active power difference between pypower and pandapower: "
        "%.2e MW" % max_(abs(diff_res["branch"][:, [0, 2]])))
    logger.debug(
        "Maximum branch flow reactive power difference between pypower and "
        "pandapower: %.2e MVAr" % max_(abs(diff_res["branch"][:, [1, 3]])))
    logger.debug(
        "Maximum active power generation difference between pypower and pandapower: "
        "%.2e MW" % max_(abs(diff_res["gen"][:, 0])))
    logger.debug(
        "Maximum reactive power generation difference between pypower and pandapower: "
        "%.2e MVAr" % max_(abs(diff_res["gen"][:, 1])))
    if _validate_diff_res(diff_res, {"bus_vm_pu": 1e-3, "bus_va_degree": 1e-3, "branch_p_mw": 1e-6,
                                     "branch_q_mvar": 1e-6}) and \
            (max_(abs(diff_res["gen"])) > 1e-1).any():
        logger.debug(
            "The active/reactive power generation difference possibly results "
            "because of a pypower error. Please validate "
            "the results via pypower loadflow."
        )  # this occurs e.g. at ppc case9
    # give a return
    if isinstance(max_diff_values, dict):
        return _validate_diff_res(diff_res, max_diff_values)
    else:
        logger.debug("'max_diff_values' must be a dict.")
Index = Testsys["gen"][0:sizegenbus, :]  # 将前17台机组的数据取出
Index[:, 0:10] = np.hstack(
    (Testsys["bus"][genbus,
                    1].reshape(-1,
                               1), -Testsys["bus"][genbus, 3].reshape(-1, 1),
     -Testsys["bus"][genbus, 4].reshape(-1, 1), np.zeros(
         (sizegenbus, 1)), -Testsys["bus"][genbus, 4].reshape(-1, 1),
     np.zeros((sizegenbus, 1)).reshape(-1, 1), Testsys["baseMVA"] * np.ones(
         (sizegenbus, 1)), np.ones((sizegenbus, 1)), np.zeros(
             (sizegenbus, 1)), -Testsys["bus"][genbus, 3].reshape(-1, 1)))
Testsys["gen"] = np.append(Testsys["gen"], Index, axis=0)
del Index
Testsys["bus"][genbus, 2:4] = 0  # 将原来的节点有功、无功负荷设为零
totalprob = failprob()
ppopt = ppoption(PF_DC=1, VERBOSE=0, OUT_ALL=0, OPF_ALG_DC=200, OPF_FLOW_LIM=1)
result = runopf(casedata=Testsys, ppopt=ppopt)
while (betavalue > BETAlimit) & (iter < ITER_max):
    eqstatus_indi = mc_sampling(totalprob, SIMUNIT, Ng, Nl)
    aa = np.ones((eqstatus_indi.shape[0], 1))
    bb = np.zeros((eqstatus_indi.shape[0], 2))
    eqstatus_indi = np.hstack((eqstatus_indi, aa, bb))
    eqstatus_indi, ia1 = np.unique(eqstatus_indi, axis=0,
                                   return_inverse=True)  # 找出抽样中的相同结果
    for i in range(eqstatus_indi.shape[0]):
        eqstatus_indi[i, Ng + Nl] = sum(ia1 == i)  # 将重复记录次数在第Ng + Nl + 1
    if iter:
        x = 0
        for i in range(eqstatus_indi.shape[0]):
            aa = eqstatus_indi[x, 0:Ng + Nl]
            for j in range(row_index - 1):
                if (aa == eqstatus_total[j, 0:Ng + Nl]).all():
Ejemplo n.º 16
0
def t_opf_pips(quiet=False):
    """Tests for PIPS-based AC optimal power flow.

    @author: Ray Zimmerman (PSERC Cornell)
    """
    num_tests = 101

    t_begin(num_tests, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case9_opf')
    verbose = 0#not quiet

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

    ## 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])

    ## get solved AC power flow case from MAT-file
    soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf['bus_soln']
    gen_soln = soln9_opf['gen_soln']
    branch_soln = soln9_opf['branch_soln']
    f_soln = soln9_opf['f_soln'][0]

    ## run OPF
    t = t0
    r = runopf(casefile, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    ## run with automatic conversion of single-block pwl to linear costs
    t = ''.join([t0, '(single-block PWL) : '])
    ppc = loadcase(casefile)
    ppc['gencost'][2, NCOST] = 2
    r = runopf(ppc, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    xr = r_[r['var']['val']['Va'], r['var']['val']['Vm'], r['var']['val']['Pg'],
            r['var']['val']['Qg'], 0, r['var']['val']['y']]
    t_is(r['x'], xr, 8, [t, 'check on raw x returned from OPF'])

    ## get solved AC power flow case from MAT-file
    soln9_opf_Plim = loadmat(join(tdir, 'soln9_opf_Plim.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_Plim['bus_soln']
    gen_soln = soln9_opf_Plim['gen_soln']
    branch_soln = soln9_opf_Plim['branch_soln']
    f_soln = soln9_opf_Plim['f_soln'][0]

    ## run OPF with active power line limits
    t = ''.join([t0, '(P line lim) : '])
    ppopt1 = ppoption(ppopt, OPF_FLOW_LIM=1)
    r = runopf(casefile, ppopt1)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    ##-----  test OPF with quadratic gen costs moved to generalized costs  -----
    ppc = loadcase(casefile)
    ppc['gencost'] = array([
        [2,   1500, 0,   3,   0.11,    5,   0],
        [2,   2000, 0,   3,   0.085,   1.2, 0],
        [2,   3000, 0,   3,   0.1225,  1,   0]
    ])
    r = runopf(ppc, ppopt)
    bus_soln, gen_soln, branch_soln, f_soln, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    branch_soln = branch_soln[:, :MU_ST + 1]

    A = None
    l = array([])
    u = array([])
    nb = ppc['bus'].shape[0]      # number of buses
    ng = ppc['gen'].shape[0]      # number of gens
    thbas = 0;                thend    = thbas + nb
    vbas     = thend;     vend     = vbas + nb
    pgbas    = vend;      pgend    = pgbas + ng
#    qgbas    = pgend;     qgend    = qgbas + ng
    nxyz = 2 * nb + 2 * ng
    N = sparse((ppc['baseMVA'] * ones(ng), (arange(ng), arange(pgbas, pgend))), (ng, nxyz))
    fparm = ones((ng, 1)) * array([[1, 0, 0, 1]])
    ix = argsort(ppc['gen'][:, 0])
    H = 2 * spdiags(ppc['gencost'][ix, 4], 0, ng, ng, 'csr')
    Cw = ppc['gencost'][ix, 5]
    ppc['gencost'][:, 4:7] = 0

    ## run OPF with quadratic gen costs moved to generalized costs
    t = ''.join([t0, 'w/quadratic generalized gen cost : '])
    r = opf(ppc, A, l, u, ppopt, N, fparm, H, Cw)
    f, bus, gen, branch, success = \
            r['f'], r['bus'], r['gen'], r['branch'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    t_is(r['cost']['usr'], f, 12, [t, 'user cost'])

    ##-----  run OPF with extra linear user constraints & costs  -----
    ## single new z variable constrained to be greater than or equal to
    ## deviation from 1 pu voltage at bus 1, linear cost on this z
    ## get solved AC power flow case from MAT-file
    soln9_opf_extras1 = loadmat(join(tdir, 'soln9_opf_extras1.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_extras1['bus_soln']
    gen_soln = soln9_opf_extras1['gen_soln']
    branch_soln = soln9_opf_extras1['branch_soln']
    f_soln = soln9_opf_extras1['f_soln'][0]

    row = [0, 0, 1, 1]
    col = [9, 24, 9, 24]
    A = sparse(([-1, 1, 1, 1], (row, col)), (2, 25))
    u = array([Inf, Inf])
    l = array([-1, 1])

    N = sparse(([1], ([0], [24])), (1, 25))    ## new z variable only
    fparm = array([[1, 0, 0, 1]])              ## w = r = z
    H = sparse((1, 1))                ## no quadratic term
    Cw = array([100.0])

    t = ''.join([t0, 'w/extra constraints & costs 1 : '])
    r = opf(casefile, A, l, u, ppopt, N, fparm, H, Cw)
    f, bus, gen, branch, success = \
            r['f'], r['bus'], r['gen'], r['branch'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    t_is(r['var']['val']['z'], 0.025419, 6, [t, 'user variable'])
    t_is(r['cost']['usr'], 2.5419, 4, [t, 'user cost'])

    ##-----  test OPF with capability curves  -----
    ppc = loadcase(join(tdir, 't_case9_opfv2'))
    ## remove angle diff limits
    ppc['branch'][0, ANGMAX] =  360
    ppc['branch'][8, ANGMIN] = -360

    ## get solved AC power flow case from MAT-file
    soln9_opf_PQcap = loadmat(join(tdir, 'soln9_opf_PQcap.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_PQcap['bus_soln']
    gen_soln = soln9_opf_PQcap['gen_soln']
    branch_soln = soln9_opf_PQcap['branch_soln']
    f_soln = soln9_opf_PQcap['f_soln'][0]

    ## run OPF with capability curves
    t = ''.join([t0, 'w/capability curves : '])
    r = runopf(ppc, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    ##-----  test OPF with angle difference limits  -----
    ppc = loadcase(join(tdir, 't_case9_opfv2'))
    ## remove capability curves
    ppc['gen'][ix_(arange(1, 3),
                   [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX])] = zeros((2, 6))

    ## get solved AC power flow case from MAT-file
    soln9_opf_ang = loadmat(join(tdir, 'soln9_opf_ang.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf_ang['bus_soln']
    gen_soln = soln9_opf_ang['gen_soln']
    branch_soln = soln9_opf_ang['branch_soln']
    f_soln = soln9_opf_ang['f_soln'][0]

    ## run OPF with angle difference limits
    t = ''.join([t0, 'w/angle difference limits : '])
    r = runopf(ppc, ppopt)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  1, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])
    t_is(branch[:, ibr_angmu ], branch_soln[:, ibr_angmu ],  2, [t, 'branch angle mu'])

    ##-----  test OPF with ignored angle difference limits  -----
    ## get solved AC power flow case from MAT-file
    soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True)
    ## defines bus_soln, gen_soln, branch_soln, f_soln
    bus_soln = soln9_opf['bus_soln']
    gen_soln = soln9_opf['gen_soln']
    branch_soln = soln9_opf['branch_soln']
    f_soln = soln9_opf['f_soln'][0]

    ## run OPF with ignored angle difference limits
    t = ''.join([t0, 'w/ignored angle difference limits : '])
    ppopt1 = ppoption(ppopt, OPF_IGNORE_ANG_LIM=1)
    r = runopf(ppc, ppopt1)
    bus, gen, branch, f, success = \
            r['bus'], r['gen'], r['branch'], r['f'], r['success']
    ## ang limits are not in this solution data, so let's remove them
    branch[0, ANGMAX] =  360
    branch[8, ANGMIN] = -360
    t_ok(success, [t, 'success'])
    t_is(f, f_soln, 3, [t, 'f'])
    t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
    t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
    t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
    t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
    t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
    t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
    t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
    t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
    t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
    t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

    t_end()