def t_makeLODF(quiet=False): """Tests for C{makeLODF}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ntests = 31 t_begin(ntests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_auction_case') verbose = 0 #not quiet ## load case ppc = loadcase(casefile) ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) r = rundcopf(ppc, ppopt) baseMVA, bus, gen, branch = r['baseMVA'], r['bus'], r['gen'], r['branch'] _, bus, gen, branch = ext2int1(bus, gen, branch) ## compute injections and flows F0 = branch[:, PF] ## create some PTDF matrices H = makePTDF(baseMVA, bus, branch, 0) ## create some PTDF matrices try: LODF = makeLODF(branch, H) except ZeroDivisionError: pass ## take out non-essential lines one-by-one and see what happens ppc['bus'] = bus ppc['gen'] = gen branch0 = branch outages = r_[arange(12), arange(13, 15), arange(16, 18), [19], arange(26, 33), arange(34, 41)] for k in outages: ppc['branch'] = branch0.copy() ppc['branch'][k, BR_STATUS] = 0 r, _ = rundcpf(ppc, ppopt) baseMVA, bus, gen, branch = \ r['baseMVA'], r['bus'], r['gen'], r['branch'] F = branch[:, PF] t_is(LODF[:, k], (F - F0) / F0[k], 6, 'LODF[:, %d]' % k) t_end()
def t_makeLODF(quiet=False): """Tests for C{makeLODF}. @author: Ray Zimmerman (PSERC Cornell) @author: Richard Lincoln """ ntests = 31 t_begin(ntests, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_auction_case') verbose = 0#not quiet ## load case ppc = loadcase(casefile) ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) r = rundcopf(ppc, ppopt) baseMVA, bus, gen, branch = r['baseMVA'], r['bus'], r['gen'], r['branch'] _, bus, gen, branch = ext2int1(bus, gen, branch) ## compute injections and flows F0 = branch[:, PF] ## create some PTDF matrices H = makePTDF(baseMVA, bus, branch, 0) ## create some PTDF matrices try: LODF = makeLODF(branch, H) except ZeroDivisionError: pass ## take out non-essential lines one-by-one and see what happens ppc['bus'] = bus ppc['gen'] = gen branch0 = branch outages = r_[arange(12), arange(13, 15), arange(16, 18), [19], arange(26, 33), arange(34, 41)] for k in outages: ppc['branch'] = branch0.copy() ppc['branch'][k, BR_STATUS] = 0 r, _ = rundcpf(ppc, ppopt) baseMVA, bus, gen, branch = \ r['baseMVA'], r['bus'], r['gen'], r['branch'] F = branch[:, PF] t_is(LODF[:, k], (F - F0) / F0[k], 6, 'LODF[:, %d]' % k) t_end()
def solve_dcpf(case, hour=None, results=None, ppopt=None, fname='./runpf.log'): ppopt = ppoption(ppopt) fname = os.path.abspath(fname) baseMVA = case.baseMVA bus = case.bus.copy(deep=True) branch = case.branch.copy(deep=True) gen = case.gen.copy(deep=True) gencost = case.gen.copy(deep=True) if hour is not None: logger.debug("Setting bus load based on case.load") bus['PD'] = case.load.loc[hour] bus = bus.fillna(0) if hour is not None and results is not None: logger.debug("Setting GEN_STATUS and PG") gen['GEN_STATUS'] = results.unit_commitment.loc[hour].astype(int) gen['PG'] = results.power_generated.loc[hour] value = [i + 1 for i in range(0, len(bus.index))] bus_name = bus.index bus.index = value bus.index = bus.index.astype(int) branch['F_BUS'] = branch['F_BUS'].apply(lambda x: value[bus_name.get_loc(x)]).astype(int) branch['T_BUS'] = branch['T_BUS'].apply(lambda x: value[bus_name.get_loc(x)]).astype(int) gen['GEN_BUS'] = gen['GEN_BUS'].apply(lambda x: value[bus_name.get_loc(x)]).astype(int) bus = np.array(bus.reset_index()) branch = np.array(branch) gen = np.array(gen) gencost = np.array(gencost) casedata = {'baseMVA': baseMVA, 'gencost': gencost, 'gen': gen, 'branch': branch, 'bus': bus} return rundcpf(casedata, ppopt=ppopt, fname=fname)
def t_pf(quiet=False): """Tests for power flow solvers. @author: Ray Zimmerman (PSERC Cornell) """ t_begin(33, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_pf') verbose = not quiet ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] ## run Newton PF t = 'Newton PF : '; ppopt = ppoption(ppopt, PF_ALG=1) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (XB version) t = 'Fast Decoupled (XB) PF : '; ppopt = ppoption(ppopt, PF_ALG=2) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (BX version) t = 'Fast Decoupled (BX) PF : '; ppopt = ppoption(ppopt, PF_ALG=3) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run Gauss-Seidel PF t = 'Gauss-Seidel PF : '; ppopt = ppoption(ppopt, PF_ALG=4) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 5, [t, 'bus']) t_is(gen, gen_soln, 5, [t, 'gen']) t_is(branch, branch_soln, 5, [t, 'branch']) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_dcpf = loadmat(join(tdir, 'soln9_dcpf.mat'), struct_as_record=False) bus_soln = soln9_dcpf['bus_soln'] gen_soln = soln9_dcpf['gen_soln'] branch_soln = soln9_dcpf['branch_soln'] ## run DC PF t = 'DC PF : ' results, success = rundcpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## check Qg distribution, when Qmin = Qmax t = 'check Qg : ' ppopt = ppoption(ppopt, PF_ALG=1, VERBOSE=0) ppc = loadcase(casefile) ppc['gen'][0, [QMIN, QMAX]] = [20, 20] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0, QG], 24.07, 2, [t, 'single gen, Qmin = Qmax']) ppc['gen'] = r_[array([ ppc['gen'][0, :] ]), ppc['gen']] ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [ 0, 50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [10, 14.07], 2, [t, '2 gens, Qmin = Qmax for one']) ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [-50, -50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [12.03, 12.03], 2, [t, '2 gens, Qmin = Qmax for both']) ppc['gen'][0, [QMIN, QMAX]] = [0, 50] ppc['gen'][1, [QMIN, QMAX]] = [0, 100] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [8.02, 16.05], 2, [t, '2 gens, proportional']) ppc['gen'][0, [QMIN, QMAX]] = [-50, 0] ppc['gen'][1, [QMIN, QMAX]] = [50, 150] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [-50 + 8.02, 50 + 16.05], 2, [t, '2 gens, proportional']) ## network with islands t = 'network w/islands : DC PF : ' ppc0 = loadcase(casefile) ppc0['gen'][0, PG] = 60 ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] = \ ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] / 2 ppc0['gen'] = r_[array([ ppc0['gen'][0, :] ]), ppc0['gen']] ppc1 = ppc0.copy() ppc = ppc0.copy() nb = ppc['bus'].shape[0] ppc1['bus'][:, BUS_I] = ppc1['bus'][:, BUS_I] + nb ppc1['branch'][:, F_BUS] = ppc1['branch'][:, F_BUS] + nb ppc1['branch'][:, T_BUS] = ppc1['branch'][:, T_BUS] + nb ppc1['gen'][:, GEN_BUS] = ppc1['gen'][:, GEN_BUS] + nb ppc['bus'] = r_[ppc['bus'], ppc1['bus']] ppc['branch'] = r_[ppc['branch'], ppc1['branch']] ppc['gen'] = r_[ppc['gen'], ppc1['gen']] #ppopt = ppoption(ppopt, OUT_BUS=1, OUT_GEN=1, OUT_ALL=-1, VERBOSE=2) ppopt = ppoption(ppopt, VERBOSE=verbose) r = rundcpf(ppc, ppopt) t_is(r['bus'][ :9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][10:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][ :4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t = 'network w/islands : AC PF : ' ## get solved AC power flow case from MAT-file soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] r = runpf(ppc, ppopt) t_is(r['bus'][ :9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][9:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][ :4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t_end()
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()
lambda x: value[bus_name.get_loc(x)]).astype(int) bus = np.array(bus.reset_index()) branch = np.array(branch) gen = np.array(gen) gencost = np.array(gencost) casedata = { 'baseMVA': baseMVA, 'gencost': gencost, 'gen': gen, 'branch': branch, 'bus': bus } return rundcpf(casedata, ppopt=ppopt, fname=fname) def solve_dcpf(case, hour=None, results=None, ppopt={'VERBOSE': False}, fname='./runpf.log'): fname = os.path.abspath(fname) baseMVA = case.baseMVA bus = case.bus.copy(deep=True) branch = case.branch.copy(deep=True) gen = case.gen.copy(deep=True) gencost = case.gen.copy(deep=True)
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 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.")
def t_pf(quiet=False): """Tests for power flow solvers. @author: Ray Zimmerman (PSERC Cornell) """ t_begin(33, quiet) tdir = dirname(__file__) casefile = join(tdir, 't_case9_pf') verbose = not quiet ppopt = ppoption(VERBOSE=verbose, OUT_ALL=0) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] ## run Newton PF t = 'Newton PF : ' ppopt = ppoption(ppopt, PF_ALG=1) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (XB version) t = 'Fast Decoupled (XB) PF : ' ppopt = ppoption(ppopt, PF_ALG=2) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run fast-decoupled PF (BX version) t = 'Fast Decoupled (BX) PF : ' ppopt = ppoption(ppopt, PF_ALG=3) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## run Gauss-Seidel PF t = 'Gauss-Seidel PF : ' ppopt = ppoption(ppopt, PF_ALG=4) results, success = runpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 5, [t, 'bus']) t_is(gen, gen_soln, 5, [t, 'gen']) t_is(branch, branch_soln, 5, [t, 'branch']) ## get solved AC power flow case from MAT-file ## defines bus_soln, gen_soln, branch_soln soln9_dcpf = loadmat(join(tdir, 'soln9_dcpf.mat'), struct_as_record=False) bus_soln = soln9_dcpf['bus_soln'] gen_soln = soln9_dcpf['gen_soln'] branch_soln = soln9_dcpf['branch_soln'] ## run DC PF t = 'DC PF : ' results, success = rundcpf(casefile, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_ok(success, [t, 'success']) t_is(bus, bus_soln, 6, [t, 'bus']) t_is(gen, gen_soln, 6, [t, 'gen']) t_is(branch, branch_soln, 6, [t, 'branch']) ## check Qg distribution, when Qmin = Qmax t = 'check Qg : ' ppopt = ppoption(ppopt, PF_ALG=1, VERBOSE=0) ppc = loadcase(casefile) ppc['gen'][0, [QMIN, QMAX]] = [20, 20] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0, QG], 24.07, 2, [t, 'single gen, Qmin = Qmax']) ppc['gen'] = r_[array([ppc['gen'][0, :]]), ppc['gen']] ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [0, 50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [10, 14.07], 2, [t, '2 gens, Qmin = Qmax for one']) ppc['gen'][0, [QMIN, QMAX]] = [10, 10] ppc['gen'][1, [QMIN, QMAX]] = [-50, -50] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [12.03, 12.03], 2, [t, '2 gens, Qmin = Qmax for both']) ppc['gen'][0, [QMIN, QMAX]] = [0, 50] ppc['gen'][1, [QMIN, QMAX]] = [0, 100] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [8.02, 16.05], 2, [t, '2 gens, proportional']) ppc['gen'][0, [QMIN, QMAX]] = [-50, 0] ppc['gen'][1, [QMIN, QMAX]] = [50, 150] results, success = runpf(ppc, ppopt) bus, gen, branch = results['bus'], results['gen'], results['branch'] t_is(gen[0:2, QG], [-50 + 8.02, 50 + 16.05], 2, [t, '2 gens, proportional']) ## network with islands t = 'network w/islands : DC PF : ' ppc0 = loadcase(casefile) ppc0['gen'][0, PG] = 60 ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] = \ ppc0['gen'][0, [PMIN, PMAX, QMIN, QMAX, PG, QG]] / 2 ppc0['gen'] = r_[array([ppc0['gen'][0, :]]), ppc0['gen']] ppc1 = ppc0.copy() ppc = ppc0.copy() nb = ppc['bus'].shape[0] ppc1['bus'][:, BUS_I] = ppc1['bus'][:, BUS_I] + nb ppc1['branch'][:, F_BUS] = ppc1['branch'][:, F_BUS] + nb ppc1['branch'][:, T_BUS] = ppc1['branch'][:, T_BUS] + nb ppc1['gen'][:, GEN_BUS] = ppc1['gen'][:, GEN_BUS] + nb ppc['bus'] = r_[ppc['bus'], ppc1['bus']] ppc['branch'] = r_[ppc['branch'], ppc1['branch']] ppc['gen'] = r_[ppc['gen'], ppc1['gen']] #ppopt = ppoption(ppopt, OUT_BUS=1, OUT_GEN=1, OUT_ALL=-1, VERBOSE=2) ppopt = ppoption(ppopt, VERBOSE=verbose) r = rundcpf(ppc, ppopt) t_is(r['bus'][:9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][10:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][:4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t = 'network w/islands : AC PF : ' ## get solved AC power flow case from MAT-file soln9_pf = loadmat(join(tdir, 'soln9_pf.mat'), struct_as_record=False) bus_soln = soln9_pf['bus_soln'] gen_soln = soln9_pf['gen_soln'] branch_soln = soln9_pf['branch_soln'] r = runpf(ppc, ppopt) t_is(r['bus'][:9, VA], bus_soln[:, VA], 8, [t, 'voltage angles 1']) t_is(r['bus'][9:18, VA], bus_soln[:, VA], 8, [t, 'voltage angles 2']) Pg = r_[gen_soln[0, PG] - 30, 30, gen_soln[1:3, PG]] t_is(r['gen'][:4, PG], Pg, 8, [t, 'active power generation 1']) t_is(r['gen'][4:8, PG], Pg, 8, [t, 'active power generation 1']) t_end()
def main(train_case, storing_dir): # Define the parameters of the training. # More informations about the distributions used during training can be found # in the notebook Sampling random power networks. train_params = { 'num_samples': 1000, 'learning_rate': 3e-3, } # Define the parameters of the model. model_params = { 'num_updates': 30, #10, 'latent_dim': 10, 'latent_layers': 2 #3 } noise_params = { 'is_noise_active': 1., 'r_min_coeff': -0.1, 'r_max_coeff': +0.1, 'x_min_coeff': -0.1, 'x_max_coeff': +0.1, 'b_min_coeff': -0.1, 'b_max_coeff': +0.1, 'ratio_min_coeff': -0.2, 'ratio_max_coeff': +0.2, 'angle_min_offset': -0.2, 'angle_max_offset': +0.2, 'Vg_min': 0.95, 'Vg_max': 1.05, 'Pd_min_coeff': -0.5, 'Pd_max_coeff': +0.5, 'Qd_min_coeff': -0.5, 'Qd_max_coeff': +0.5, 'Gs_min_coeff': -0., 'Gs_max_coeff': +0., 'Bs_min_coeff': -0., 'Bs_max_coeff': +0., } TEST_SIZE = 100 LEARN_ITER = 10 config = tf.ConfigProto() config.gpu_options.allow_growth = True config.allow_soft_placement = True config.log_device_placement = False case_list = ['case9', 'case14', 'case30', 'case118'] error_NR_list = {} error_DC_list = {} error_GNS_list = {} time_NR_list = {} time_DC_list = {} time_GNS_list = {} timestr = time.strftime("%Y-%m-%d-%Hh%Mm%Ss") expe_dir = 'expe_' + train_case + '_' + timestr try: os.stat(os.path.join(path, expe_dir)) except: os.mkdir(os.path.join(path, expe_dir)) print("Building model that will be trained on " + train_case) tf.reset_default_graph() sess = tf.Session(config=config) expe_path = os.path.join(path, expe_dir) with tf.variable_scope('GNS', reuse=tf.AUTO_REUSE): model = GNS(train_case, train_params, model_params, noise_params, expe_path, sess) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) print(" Learning on " + train_case + "...") for learn_iter in tqdm.tqdm(range(LEARN_ITER)): # Apply a gradient descent sess.run(model.opt_op) # Store the loss model.store_summary(learn_iter) print(" The model trained on " + train_case + " is ready to be tested!") all_p_nr = {} all_p_dc = {} all_p_gns = {} time_NR_list = {} time_DC_list = {} time_GNS_list = {} for test_case in case_list: print(" Testing on " + test_case + "...") model.change_default_power_grid(case=test_case) # Sample all_p_nr[test_case] = None all_p_dc[test_case] = None all_p_gns[test_case] = None time_NR_list[test_case] = [] time_DC_list[test_case] = [] time_GNS_list[test_case] = [] i = 0 while i < TEST_SIZE: print(i) # Sample a power grid gens, buses, lines, p_gen, pft, ptf, qft, qtf = sess.run([ model.gens, model.buses, model.lines, model.p_gen, model.p_from_to[str(model_params['num_updates'])], model.p_to_from[str(model_params['num_updates'])], model.q_from_to[str(model_params['num_updates'])], model.q_to_from[str(model_params['num_updates'])], ]) sample_id = 0 model.input_data['gen'][:, 1] = p_gen[str( model_params['num_updates'])][sample_id] * 100 model.input_data['gen'][:, 5] = gens['Vg'][sample_id] model.input_data['bus'][:, 2] = buses['Pd'][sample_id] model.input_data['bus'][:, 3] = buses['Qd'][sample_id] model.input_data['bus'][:, 4] = buses['Gs'][sample_id] model.input_data['bus'][:, 5] = buses['Bs'][sample_id] model.input_data['branch'][:, 2] = lines['r'][sample_id] model.input_data['branch'][:, 3] = lines['x'][sample_id] model.input_data['branch'][:, 4] = lines['b'][sample_id] model.input_data['branch'][:, 8] = lines['ratio'][sample_id] model.input_data[ 'branch'][:, 9] = lines['angle'][sample_id] * 180 / np.pi i += 1 try: start = time.time() a_nr = runpf(model.input_data) time_NR_list[test_case].append(time.time() - start) except: print('did not converge') i -= 1 continue if a_nr[0]['success'] == 0: print('did not converge') i -= 1 continue # Now try with DC approx start = time.time() a_dc = rundcpf(model.input_data) time_DC_list[test_case].append(time.time() - start) # Get flows from GNS p_from_gns = pft[sample_id] * 100 p_to_gns = ptf[sample_id] * 100 q_from_gns = qft[sample_id] * 100 q_to_gns = qtf[sample_id] * 100 if all_p_gns[test_case] is None: all_p_gns[test_case] = np.r_[p_from_gns, p_to_gns] else: all_p_gns[test_case] = np.c_[all_p_gns[test_case], np.r_[p_from_gns, p_to_gns]] # Get flows from Newton-Raphson p_from_nr = a_nr[0]['branch'][:, 13] q_from_nr = a_nr[0]['branch'][:, 14] p_to_nr = a_nr[0]['branch'][:, 15] q_to_nr = a_nr[0]['branch'][:, 16] if all_p_nr[test_case] is None: all_p_nr[test_case] = np.r_[p_from_nr, p_to_nr] else: all_p_nr[test_case] = np.c_[all_p_nr[test_case], np.r_[p_from_nr, p_to_nr]] # Get flows from DC approx p_from_dc = a_dc[0]['branch'][:, 13] q_from_dc = a_dc[0]['branch'][:, 14] p_to_dc = a_dc[0]['branch'][:, 15] q_to_dc = a_dc[0]['branch'][:, 16] if all_p_dc[test_case] is None: all_p_dc[test_case] = np.r_[p_from_dc, p_to_dc] else: all_p_dc[test_case] = np.c_[all_p_dc[test_case], np.r_[p_from_dc, p_to_dc]] # Now try with GNS v_time, theta_time = sess.run([model.v, model.theta]) start = time.time() v_time, theta_time = sess.run([model.v, model.theta]) time_GNS_list[test_case].append( (time.time() - start) / train_params['num_samples']) np.save(os.path.join(storing_dir, expe_dir + "_all_p_nr.npy"), all_p_nr) np.save(os.path.join(storing_dir, expe_dir + "_all_p_gns.npy"), all_p_gns) np.save(os.path.join(storing_dir, expe_dir + "_all_p_dc.npy"), all_p_dc) np.save(os.path.join(storing_dir, expe_dir + "_time_nr.npy"), time_NR_list) np.save(os.path.join(storing_dir, expe_dir + "_time_gns.npy"), time_GNS_list) np.save(os.path.join(storing_dir, expe_dir + "_time_dc.npy"), time_DC_list)