def __init__(self): self.action_space = [] self.ppopt = ppoption(VERBOSE=0, OUT_ALL=0, OUT_SYS_SUM=False, OUT_BUS=False, OUT_BRANCH=False) #output format control self.state = {'loss': None, 'Vmin': None, 'Vmax': None} self.bus_list = [] self.genmap = {} #{bus number: gen number} self.actmap = {} #{0~n_actions: act number} # assign case self.ppc = case() g = nx.Graph() for bus in self.ppc['bus']: self.bus_list.append(int(bus[0])) g.add_node(int(bus[0])) for brch in self.ppc['branch']: g.add_edge(int(brch[0]), int(brch[1])) self.pos = nx.kamada_kawai_layout(g) red = '#ff0000' #red green = '#00ff00' #green blue = '#0000ff' #blue self.cmap = col.LinearSegmentedColormap.from_list( 'cmap', [blue, green, red])
def PF_Sim(ppc, pDemand, rDemand, nodesStorage, U, rootV2): """ Uses PyPower to calculate PF to simulate node voltages after storage action Inputs: ppc - PyPower case dictionary pDemand/rDemand - true values of real and reactive power demanded nodesStorage - list of storage nodes indexes U - storage control action rootV2 - voltage of the substation node Outputs: runVoltage - (buses X time) array of voltages """ nodesNum = 7 #pDemand.shape tuple doesnt work... runVoltage = np.zeros((nodesNum, 1)) pLoad = np.copy(pDemand) pLoad[nodesStorage] = pLoad[nodesStorage] + U rLoad = rDemand rootVoltage = np.sqrt(rootV2) ppc['bus'][:, 2] = pLoad.flatten() ppc['bus'][:, 3] = rLoad.flatten() #ppc['bus'][rootIdx,7] = rootVoltage # Doesnt actually set PF root voltage ppopt = ppoption(VERBOSE=0, OUT_ALL=0) ppc_out = runpf(ppc, ppopt) rootVdiff = rootVoltage - 1 runVoltage = ppc_out[0]['bus'][:, 7] + rootVdiff return runVoltage
def case_iteration(): ppc = mycase() ppopt = ppoption(PF_ALG=2) r = runopf(ppc, ppopt) myprintpf(r)
def PF_Sim(ppc, GCtime, pDemand, rDemand, nodesStorage, U, rootV2): """ Uses PyPower to calculate PF to simulate node voltages after storage control Inputs: ppc - PyPower case dictionary GCtime - number of time steps between GC runs pDemand/rDemand - true values of real and reactive power demanded nodesStorage - list of storage nodes indexes U - storage control action rootV2 - voltage of the substation node Outputs: runVoltage - (buses X time) array of voltages """ nodesNum, T = pDemand.shape runVoltage = np.zeros((nodesNum, GCtime)) for t in range(GCtime): pLoad = pDemand[:, t] pLoad[nodesStorage] = pLoad[nodesStorage] + U[:, t] rLoad = rDemand[:, t] rootVoltage = np.sqrt(rootV2[:, t]) ppc['bus'][:, 2] = pLoad.flatten() ppc['bus'][:, 3] = rLoad.flatten() # ppc['bus'][rootIdx,7] = rootVoltage # Doesnt actually set PF root voltage # for surpressing runpf output ppopt = ppoption(VERBOSE=0, OUT_ALL=0) ppc_out = runpf(ppc, ppopt) rootVdiff = rootVoltage - 1 runVoltage[:, t] = ppc_out[0]['bus'][:, 7] + rootVdiff return runVoltage
def adapt_case(node, power, time): #input node is the node that the agent accesses, the power is in kW , the time is the timestep [0,96] time = time % 96 # if the time interval exceeds the number of elements in the load profile loadprofile = 0.001 * array([ 2.1632, 1.9456, 1.7568, 1.5968, 1.4784, 1.3952, 1.3408, 1.3056, 1.2832, 1.2672, 1.2608, 1.2512, 1.2416, 1.2352, 1.2256, 1.2256, 1.2288, 1.2416, 1.2576, 1.28, 1.3088, 1.3792, 1.5264, 1.7856, 2.176, 2.6496, 3.136, 3.568, 3.8912, 4.112, 4.2464, 4.3136, 4.3328, 4.3136, 4.2592, 4.1824, 4.0864, 3.9872, 3.888, 3.808, 3.7536, 3.7184, 3.7024, 3.7024, 3.7152, 3.744, 3.7984, 3.888, 4.0128, 4.1472, 4.256, 4.3136, 4.2944, 4.2144, 4.096, 3.968, 3.8464, 3.7376, 3.6384, 3.5424, 3.4528, 3.376, 3.312, 3.2768, 3.2704, 3.3024, 3.3792, 3.5168, 3.712, 3.9584, 4.2432, 4.5536, 4.8768, 5.1904, 5.4784, 5.7248, 5.9104, 6.0224, 6.0448, 5.9648, 5.7824, 5.5264, 5.2448, 4.9792, 4.7648, 4.5888, 4.4288, 4.2624, 4.0704, 3.856, 3.6256, 3.3824, 3.136, 2.8864, 2.64, 2.3968 ]) q = zeros(25) #set the reactive power to zero at each point p = loadprofile[time] * ones( 25 ) # set the active power at each grid point to the value in the load profile given the time p[0] = 0 # set the load at the transformer to 0 p[node] = p[ node] + power * 0.001 # add the power to the node that the agent controlls # do the actual power flow simulation ppc = casemodul(p, q) ppopt = ppoption(PF_ALG=2, VERBOSE=False, OUT_ALL=0) ppc_result, y = runpf( ppc, ppopt) #run the powerflow simulation gibven the case and the options return ppc_result["bus"][node, 7]
def run_pypower(case): """ Executes a PYPOWER power flow for *case* and writes its results back to *case*. If *case* is a string, :func:`transform` will be called first to create a bus/branch model from the CIM file. """ basestring = (str,bytes) from pypower.api import ppoption, runpf from cim2busbranch import ext_pypower if isinstance(case, basestring): case = transform(case) ppc = ext_pypower.create(case) ppo = ppoption(OUT_ALL=0, VERBOSE=0) res = runpf(ppc, ppo) if not res[1]: raise RuntimeError('PYPOWER power flow failed.') ext_pypower.write_results_to_case(res[0], case)
def test_pypower_case(): #ppopt is a dictionary with the details of the optimization routine to run ppopt = ppoption(PF_ALG=2) #choose DC or AC ppopt["PF_DC"] = True #ppc is a dictionary with details about the network, including baseMVA, branches and generators ppc = case() results, success = runpf(ppc, ppopt) #store results in a DataFrame for easy access results_df = {} #branches columns = 'bus0, bus1, r, x, b, rateA, rateB, rateC, ratio, angle, status, angmin, angmax, p0, q0, p1, q1'.split( ", ") results_df['branch'] = pd.DataFrame(data=results["branch"], columns=columns) #buses columns = [ "bus", "type", "Pd", "Qd", "Gs", "Bs", "area", "v_mag_pu_set", "v_ang_set", "v_nom", "zone", "Vmax", "Vmin" ] results_df['bus'] = pd.DataFrame(data=results["bus"], columns=columns, index=results["bus"][:, 0]) #generators columns = "bus, p, q, q_max, q_min, Vg, mBase, status, p_max, p_min, Pc1, Pc2, Qc1min, Qc1max, Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30, ramp_q, apf".split( ", ") results_df['gen'] = pd.DataFrame(data=results["gen"], columns=columns) #now compute in PyPSA network = pypsa.Network() network.import_from_pypower_ppc(ppc) network.lpf() #compare generator dispatch p_pypsa = network.generators_t.p.loc["now"].values p_pypower = results_df['gen']["p"].values np.testing.assert_array_almost_equal(p_pypsa, p_pypower) #compare branch flows for item in ["lines", "transformers"]: df = getattr(network, item) pnl = getattr(network, item + "_t") for si in ["p0", "p1"]: si_pypsa = getattr(pnl, si).loc["now"].values si_pypower = results_df['branch'][si][df.original_index].values np.testing.assert_array_almost_equal(si_pypsa, si_pypower)
def __init__(self): self.ppc = case30() self.ppopt = ppoption(PF_ALG=1, RETURN_RAW_DER=True, OPF_FLOW_LIM=0) self.ppn = case30_panda() self.results = None self.sol_opt = None self.alg = None self.idx_mode = None self.res_struct = None self.load_list = None
def test_pypower_case(): #ppopt is a dictionary with the details of the optimization routine to run ppopt = ppoption(PF_ALG=2) #choose DC or AC ppopt["PF_DC"] = True #ppc is a dictionary with details about the network, including baseMVA, branches and generators ppc = case() results,success = runpf(ppc, ppopt) #store results in a DataFrame for easy access results_df = {} #branches columns = 'bus0, bus1, r, x, b, rateA, rateB, rateC, ratio, angle, status, angmin, angmax, p0, q0, p1, q1'.split(", ") results_df['branch'] = pd.DataFrame(data=results["branch"],columns=columns) #buses columns = ["bus","type","Pd","Qd","Gs","Bs","area","v_mag_pu_set","v_ang_set","v_nom","zone","Vmax","Vmin"] results_df['bus'] = pd.DataFrame(data=results["bus"],columns=columns,index=results["bus"][:,0]) #generators columns = "bus, p, q, q_max, q_min, Vg, mBase, status, p_max, p_min, Pc1, Pc2, Qc1min, Qc1max, Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30, ramp_q, apf".split(", ") results_df['gen'] = pd.DataFrame(data=results["gen"],columns=columns) #now compute in PyPSA network = pypsa.Network() network.import_from_pypower_ppc(ppc) network.lpf() #compare generator dispatch p_pypsa = network.generators_t.p.loc["now"].values p_pypower = results_df['gen']["p"].values np.testing.assert_array_almost_equal(p_pypsa,p_pypower) #compare branch flows for item in ["lines","transformers"]: df = getattr(network,item) pnl = getattr(network,item + "_t") for si in ["p0","p1"]: si_pypsa = getattr(pnl,si).loc["now"].values si_pypower = results_df['branch'][si][df.original_index].values np.testing.assert_array_almost_equal(si_pypsa,si_pypower)
def likelihood_ps(measur_vec,bvec): # -- modify load buses ppc["bus"][ind,2] = bvec # -- estimate the transformer measurements ppopt = pypo.ppoption(PF_ALG=2, VERBOSE=0, OUT_ALL=0) r = pypo.runpf(ppc, ppopt) estim = r[0]['gen'][:,2] # -- calculate the likelihood sig = 10.0 return np.exp(-((estim - measur_vec)**2).sum()/(2*sig**2))
def main(casefile): ppopt = ppoption(PF_ALG=2) r = runpf(casedata=casefile, ppopt=ppopt) output = {'baseMVA': r[0]['baseMVA'], 'branch': r[0]["branch"].tolist(), 'bus': r[0]["bus"].tolist(), 'gen': r[0]["gen"].tolist() } sys.stdout.write(json.dumps(output)+'\n')
def proportional_sim(grid, a, attack_set, verbose=False, saveIterations=False): """Runs a cascading failure simulation, with capacities proportional to initial load (i.e. C = (1+a)*L). See run_simulation() for more details. """ ppopt = pp.ppoption(VERBOSE=0, OUT_ALL=0) initial_grid = pp.rundcpf(grid, ppopt)[0] capacities = abs(initial_grid['branch'][:, idx_brch.PF]) * (1 + a) return run_simulation(grid, capacities, attack_set, verbose=verbose, saveIterations=saveIterations)
def iid_sim(grid, dist, attack_set, verbose=False, saveIterations=False): """Runs a cascading failure simulation, with capacities given by C = L + S, where S is a random variable drawn from a given distribution. See run_simulation() for more details. """ ppopt = pp.ppoption(VERBOSE=0, OUT_ALL=0) initial_grid = pp.rundcpf(grid, ppopt)[0] capacities = abs(initial_grid['branch'][:, idx_brch.PF]) + dist() return run_simulation(grid, capacities, attack_set, verbose=verbose, saveIterations=saveIterations)
def lnlike(theta, y): # -- modify load buses ppc["bus"][ind, 2] = theta # -- estimate the transformer measurements sol = pypo.runpf(ppc, pypo.ppoption(PF_ALG=2, VERBOSE=0, OUT_ALL=0)) estim = sol[0]["gen"][:, 2] # -- calculate the likelihood sig = 1.0 if (theta >= 0.0).all(): return -((estim - y) ** 2).sum() / (2 * sig ** 2) else: return -np.inf
def main(): import sys case = sys.argv[1] if len(sys.argv) == 2 else 'a' cases = { 'a': test_case_a, 'b': test_case_b, } case = cases[case]() ppc = ext_pypower.create(case) ppo = ppoption(OUT_ALL=0, VERBOSE=0) res = runpf(ppc, ppo) ext_pypower.write_results_to_case(res[0], case) print(case)
def dcpf(self, time=0, mpc=None, save2network=True): """ Run DC power flow """ if type(time) is int: time = self.flow_modelled.index[time] if mpc is None: mpc = self.make_mpc() mpc = rundcpf( mpc, ppoption(VERBOSE=0, OUT_ALL=-1, OUT_BUS=0, OUT_ALL_LIM=0, OUT_BRANCH=0, OUT_SYS_SUM=0)) self.solved_mpc.append(mpc) # AC exchange between areas br = mpc[0]['branch'] ac_flow = pd.DataFrame(0, index=[time], columns=list(self.flow_modelled)) bid0 = arr(self.bus.loc[br[:, 0], 'bidz']) bid1 = arr(self.bus.loc[br[:, 1], 'bidz']) for n, a0 in enumerate(self.bidz): for a1 in self.bidz[n + 1:]: ind0 = (bid0 == a0) & (bid1 == a1) # find lines between areas ind1 = (bid0 == a1) & (bid1 == a0 ) # -"- but reverse flow direction if np.sum(ind0) + np.sum(ind1) > 0: exch = -np.sum(br[ind0, 13]) + np.sum(br[ind1, 13]) ac_flow.loc[time, '%s-%s' % (a0, a1)] = exch for i in list(ac_flow): self.flow_modelled.at[time, i] = ac_flow.at[time, i] if save2network: self.mpc2network( ) # add parameters to network (flows, voltage angle etc.)
def __init__(self, Time): ''' Constructs a pypower case and inits a load profile ''' #data for the power flow self.Time = Time ## might be a useless variable since the laod profile has been moved to the agent ##options self.ppopt = ppoption(PF_ALG=2, VERBOSE= 0,OUT_ALL=0) self.ppc = {"version": '2'} self.loadprofile = array([2.1632,1.9456,1.7568,1.5968,1.4784 ,1.3952,1.3408,1.3056,1.2832,1.2672, 1.2608,1.2512,1.2416,1.2352,1.2256, 1.2256,1.2288,1.2416,1.2576,1.28, 1.3088,1.3792,1.5264,1.7856,2.176, 2.6496,3.136,3.568,3.8912,4.112, 4.2464,4.3136,4.3328,4.3136,4.2592, 4.1824,4.0864,3.9872,3.888,3.808, 3.7536,3.7184,3.7024,3.7024,3.7152, 3.744,3.7984,3.888,4.0128,4.1472, 4.256,4.3136,4.2944,4.2144,4.096, 3.968,3.8464,3.7376,3.6384,3.5424, 3.4528,3.376,3.312,3.2768,3.2704, 3.3024,3.3792,3.5168,3.712,3.9584, 4.2432,4.5536,4.8768,5.1904,5.4784, 5.7248,5.9104,6.0224,6.0448,5.9648, 5.7824,5.5264,5.2448,4.9792,4.7648, 4.5888,4.4288,4.2624,4.0704,3.856, 3.6256,3.3824,3.136,2.8864,2.64, 2.3968]) ## system MVA base self.ppc["baseMVA"] = 0.144 #self.ppc["baseMVA"] = 7 ## bus data # bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin self.ppc["bus"] = array([ [1,3,0,0,0,0,0,1,1,0,1,1.1,0.94], [2,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [3,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [4,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [5,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [6,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [7,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [8,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [9,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [10,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [11,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [12,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [13,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [14,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [15,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [16,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [17,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [18,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [19,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [20,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [21,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [22,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [23,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [24,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [25,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [26,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [27,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [28,1,0,0,0,0,0,1,1,0,1,1.1,0.94], [29,1,0,0,0,0,0,1,1,0,1,1.1,0.94] ]) self.ppc["bus"][:,12] = 0.96 #self.ppc["bus"][:,12]=0.90 # relaxes the lower voltage constraint. ## generator data # bus, Pg, Qg, Qmax, Qmin, Vg, mBase, status, Pmax, Pmin, Pc1, Pc2, # Qc1min, Qc1max, Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30, ramp_q, apf self.ppc["branch"] = array([ [2,1,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [3,2,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [4,3,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [5,4,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [6,5,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [7,6,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [8,7,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [9,1,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [10,9,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [11,10,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [12,11,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [13,12,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [14,13,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [15,14,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [16,1,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [17,16,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [18,17,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [19,18,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [20,19,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [21,20,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [22,21,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [23,1,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [24,23,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [25,24,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [26,25,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [27,26,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [28,27,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360], [29,28,0.001590, 0.000814,0,0,0,0,0,0,1,-360,360] ]) self.ppc["branch"][:,2]= (0.494 * 0.097 / 1.5) self.ppc["branch"][:,3]= (0.0883 * 0.097 / 1.5) ## generator data # bus, Pg, Qg, Qmax, Qmin, Vg, mBase, status, Pmax, Pmin, Pc1, Pc2, # Qc1min, Qc1max, Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30, ramp_q, apf self.ppc["gen"] = array([ [1, 1, 0, 0, -1, 1.0, 100, 1, 5,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [3, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [4, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [6, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [7, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [8, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [9, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [10, 0, 0,0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [11, 0, 0,0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [12, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [13, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [14, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [15, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [16, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [17, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [18, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [19, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [20, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [21, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [22, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [23, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [24, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [25, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [26, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [27, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [28, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [29, 0, 0, 0, -1, 1.0, 100, 1,0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]) self.ppc["gen"][:,9] = -1 self.ppc["gen"][:,4]=1 self.power_slopes = array([-0.00022311, -0.00044879, -0.00067714, -0.00090823, -0.00114216, -0.00137904, -0.00161895] ) self.dispatch_load = zeros(29)
"case9Q", \ "case14", \ "case24_ieee_rts", \ "case30", \ "case30pwl", \ "case30Q",\ "case39",\ "case57",\ "case118"] cc = 0 #select test case casea = __import__(testdata[cc]) ########################### ppopt = ppoption(OUT_ALL=0) #0=do not print output on screen outage = imout.imout() #outage data nbus_out = len(outage["bus"]) ngen_out = len(outage["gen"]) nbr_out = len(outage["branch"]) n_tot = nbus_out + ngen_out + nbr_out #total number of outages success = [] #intialize success of load flow n_out = 1 #initialize outage counter # simulate bus outages c = 0 # start counter while c < nbus_out: temp = casea.casef() # initialize orignal testcase data
nwalkers = 300 nsteps = 100 cut = 50 # -- intialize the 14-bus system ppc0 = get_ppc14(1, 0, 1) # 0 implies no change ppc = cp.deepcopy(ppc0) # y = ppc0['gen'][:,2].copy() # default measured values of transformers ind = ppc0["bus"][:, 1] == 1 # building indices # binit = ppc0["bus"][ind,2].copy() for val in [1.00, 2.00, 5.00, 10.00, 20.00]: # -- Initialize sample print("initializing sampler...") np.random.seed(314) ppc["bus"][ind, 2] = val * np.ones(ndim) sol = pypo.runpf(ppc, pypo.ppoption(PF_ALG=2, VERBOSE=0, OUT_ALL=0)) y = sol[0]["gen"][:, 2] binit = ppc["bus"][ind, 2].copy() sampler = emcee.EnsembleSampler(nwalkers, ndim, lnlike, args=[y]) pos = np.array([binit * (1.0 + 0.2 * np.random.randn(ndim)) for i in range(nwalkers)]).clip(min=0.0) # -- run walkers print("running walkers...") sampler.run_mcmc(pos, nsteps) print("walkers finished...") # -- save chain oname = "./output/random_test20percent_diffValues" + str(val) + ".npy" print("saving chain to {0}".format(oname)) np.save(oname, sampler.chain)
def run_simulation(grid, capacities, attack_set, verbose=False, saveIterations=False): """Runs a cascading failure simulation. addition documentation goes here INPUT: grid: dict (representing a PYPOWER case file), capacities: list (of the same length as grid['branch']), attack_set: list (of line indices), verbose: bool, step_limit: int OUTPUT: dict (containing data about the simulation) """ # initialization if 'areas' in grid: del grid['areas'] ppopt = pp.ppoption(VERBOSE=0, OUT_ALL=0) grid = pp.rundcpf(grid, ppopt)[0] # record initial data initial_power = sum(grid['bus'][:, idx_bus.PD]) initial_size = len(grid['branch']) # initialize data structures failed_lines = [] failure_history = [] new_failed_lines = attack_set components = [] if saveIterations: grid_history = [copy.deepcopy(grid)] if verbose: counter = 0 print("Initial system summary:") print(system_summary(grid, [grid], capacities)) print("Lines to fail: %s" % new_failed_lines) while len(new_failed_lines) > 0: if verbose: print() temp = input("About to run loop %d. Press enter to continue." % counter) # keep track of failed lines failure_history.append(new_failed_lines) failed_lines.extend(new_failed_lines) # fail lines for line in new_failed_lines: grid['branch'][line][idx_brch.BR_R] = np.inf grid['branch'][line][idx_brch.BR_X] = np.inf # rescale power and run DC power flow in each component components = get_components(grid) for i, component in enumerate(components): rescale_power_gen(component) if len(component['branch']) > 0: components[i] = pp.rundcpf(component, ppopt)[0] # recombine components back to grid grid = combine_components(components, grid) # find failed lines new_failed_lines = [] for i in range(len(grid['branch'])): if abs(grid['branch'][i][idx_brch.PF]) > capacities[i]: new_failed_lines.append(i) if verbose: print(system_summary(grid, components, capacities)) print("Lines to fail: %s" % new_failed_lines) counter += 1 if saveIterations: grid_history.append(copy.deepcopy(grid)) # compute power loss final_power = sum(grid['bus'][:, idx_bus.PD]) power_loss = (initial_power - final_power) / initial_power #compute system size final_size = initial_size - len(failed_lines) system_size = final_size / initial_size # find isolated (no power generated) components and buses isolated_components = [] isolated_buses = [] for component in components: component_gen = sum(component['gen'][:, idx_gen.PG]) if component_gen == 0: isolated_components.append(component) for bus in component['bus']: isolated_buses.append(bus) output_data = { "failure_history": failure_history, "failed_lines": failed_lines, "system_size": system_size, "power_loss": power_loss, "components": components, "isolated_components": isolated_components, "isolated_buses": isolated_buses, "grid": grid, "capacities": capacities } if saveIterations: output_data["grid_history"] = grid_history return output_data
def avg_line_flow(ppc): ppc = pp.rundcpf(ppc, pp.ppoption(VERBOSE=0, OUT_ALL=0))[0] return np.mean(abs(ppc['branch'][:, idx_brch.PF]))
fname = "Net1_UKGDS_60_subgrid.m" fnameWhole = "Net1_UKGDS_60.m" convert_mcase(fname) from Net1_UKGDS_60_subgrid import Net1_UKGDS_60_ as net from Net1_UKGDS_60 import Net1_UKGDS_60_ as netWhole t_f = 96 # time variation t_ges = 1440 # all time in min delta_t = 15 # time intervals in min time = np.arange(delta_t, t_ges + delta_t, delta_t) casedataWhole = netWhole() convert_to_python_indices(casedataWhole) ppc = casedataWhole ppopt = ppoption(PF_ALG=2) ppc = ext2int(ppc) baseMVA, bus, gen, branch = ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc[ "branch"] baseMVA = 1000 Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch) # nodal admittance matrix Ybus condition = np.hstack((1, np.arange(16, 27, 1))) Yws = Ybus[np.ix_(condition, condition)] #Yws = Y t_f = 96 slack_idx = 0 p0 = 1e-3 iterstop = 50 accuracy = 1e-9 roundY = None
'{:.2f}'.format(unresp), '{:.2f}'.format(resp_max), '{:.8f}'.format(c2), '{:.8f}'.format(c1), '{:.1f}'.format(deg)) x = np.array(range(25)) y = np.array(load_shape) l = len(x) t = np.linspace(0, 1, l - 2, endpoint=True) t = np.append([0, 0, 0], t) t = np.append(t, [1, 1, 1]) tck_load = [t, [x, y], 3] u3 = np.linspace(0, 1, num=86400 / 300 + 1, endpoint=True) newpts = ip.splev(u3, tck_load) ppc = tesp.load_json_case(casename + '.json') ppopt_market = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=ppc['opf_dc']) ppopt_regular = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=ppc['pf_dc'], PF_MAX_IT=20, PF_ALG=1) StartTime = ppc['StartTime'] tmax = int(ppc['Tmax']) period = int(ppc['Period']) dt = int(ppc['dt']) swing_bus = int(ppc['swing_bus']) #period = 300 #dt = 15 # initialize for metrics collection
from pypower.api import case9, ppoption, runpf import numpy as np temp = case9() temp = case9() ppopt = ppoption(OUT_ALL=0) (r, s) = runpf(temp, ppopt) #(r, s) = runpf(temp) voltage = r["bus"][:, 7] angle = r["bus"][:, 8] real_gen = r["gen"][:, 1] reactive_gen = r["gen"][:, 2] real_flow_fr = r["branch"][:, 13] real_flow_to = r["branch"][:, 15] reactive_flow_fr = r["branch"][:, 14] reactive_flow_to = r["branch"][:, 16] apparent_power_flow_fr = np.sqrt(real_flow_fr**2 + reactive_flow_fr**2) apparent_power_flow_to = np.sqrt(real_flow_to**2 + reactive_flow_to**2) print type(r["success"]) print(1 - 10.0 / 100)
def pypower_loop (casefile, rootname): """ Public function to start PYPOWER solutions under control of FNCS The time step, maximum time, and other data must be set up in a JSON file. This function will run the case under FNCS, manage the FNCS message traffic, and shutdown FNCS upon completion. Five files are written: - *rootname.csv*; intermediate solution results during simulation - *rootname_m_dict.json*; metadata for post-processing - *bus_rootname_metrics.json*; bus metrics for GridLAB-D connections, upon completion - *gen_rootname_metrics.json*; bulk system generator metrics, upon completion - *sys_rootname_metrics.json*; bulk system-level metrics, upon completion Args: casefile (str): the configuring JSON file name, without extension rootname (str): the root filename for metrics output, without extension """ # if len(sys.argv) == 3: # rootname = sys.argv[1] # casefile = sys.argv[2] # else: # print ('usage: python fncsPYPOWER.py metrics_rootname casedata.json') # sys.exit() ppc = load_json_case (casefile) StartTime = ppc['StartTime'] tmax = int(ppc['Tmax']) period = int(ppc['Period']) dt = int(ppc['dt']) make_dictionary (ppc, rootname) bus_mp = open ("bus_" + rootname + "_metrics.json", "w") gen_mp = open ("gen_" + rootname + "_metrics.json", "w") sys_mp = open ("sys_" + rootname + "_metrics.json", "w") bus_meta = {'LMP_P':{'units':'USD/kwh','index':0},'LMP_Q':{'units':'USD/kvarh','index':1}, 'PD':{'units':'MW','index':2},'QD':{'units':'MVAR','index':3},'Vang':{'units':'deg','index':4}, 'Vmag':{'units':'pu','index':5},'Vmax':{'units':'pu','index':6},'Vmin':{'units':'pu','index':7}} gen_meta = {'Pgen':{'units':'MW','index':0},'Qgen':{'units':'MVAR','index':1},'LMP_P':{'units':'USD/kwh','index':2}} sys_meta = {'Ploss':{'units':'MW','index':0},'Converged':{'units':'true/false','index':1}} bus_metrics = {'Metadata':bus_meta,'StartTime':StartTime} gen_metrics = {'Metadata':gen_meta,'StartTime':StartTime} sys_metrics = {'Metadata':sys_meta,'StartTime':StartTime} gencost = ppc['gencost'] fncsBus = ppc['FNCS'] gen = ppc['gen'] ppopt_market = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=ppc['opf_dc']) ppopt_regular = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=ppc['pf_dc']) loads = np.loadtxt(ppc['CSVFile'], delimiter=',') for row in ppc['UnitsOut']: print ('unit ', row[0], 'off from', row[1], 'to', row[2], flush=True) for row in ppc['BranchesOut']: print ('branch', row[0], 'out from', row[1], 'to', row[2], flush=True) nloads = loads.shape[0] ts = 0 tnext_opf = -dt # initializing for metrics collection tnext_metrics = 0 loss_accum = 0 conv_accum = True n_accum = 0 bus_accum = {} gen_accum = {} for i in range (fncsBus.shape[0]): busnum = int(fncsBus[i,0]) bus_accum[str(busnum)] = [0,0,0,0,0,0,0,99999.0] for i in range (gen.shape[0]): gen_accum[str(i+1)] = [0,0,0] op = open (rootname + '.csv', 'w') print ('t[s],Converged,Pload,P7 (csv),Unresp (opf),P7 (rpf),Resp (opf),GLD Pub,BID?,P7 Min,V7,LMP_P7,LMP_Q7,Pgen1,Pgen2,Pgen3,Pgen4,Pdisp,Deg,c2,c1', file=op, flush=True) fncs.initialize() # transactive load components csv_load = 0 # from the file unresp = 0 # unresponsive load estimate from the auction agent resp = 0 # will be the responsive load as dispatched by OPF resp_deg = 0 # RESPONSIVE_DEG from FNCS resp_c1 = 0 # RESPONSIVE_C1 from FNCS resp_c2 = 0 # RESPONSIVE_C2 from FNCS resp_max = 0 # RESPONSIVE_MAX_MW from FNCS feeder_load = 0 # amplified feeder MW while ts <= tmax: # start by getting the latest inputs from GridLAB-D and the auction events = fncs.get_events() new_bid = False load_scale = float (fncsBus[0][2]) for topic in events: value = fncs.get_value(topic) if topic == 'UNRESPONSIVE_MW': unresp = load_scale * float(value) fncsBus[0][3] = unresp # to poke unresponsive estimate into the bus load slot new_bid = True elif topic == 'RESPONSIVE_MAX_MW': resp_max = load_scale * float(value) new_bid = True elif topic == 'RESPONSIVE_C2': resp_c2 = float(value) / load_scale new_bid = True elif topic == 'RESPONSIVE_C1': resp_c1 = float(value) new_bid = True elif topic == 'RESPONSIVE_DEG': resp_deg = int(value) new_bid = True else: gld_load = parse_mva (value) # actual value, may not match unresp + resp load feeder_load = float(gld_load[0]) * load_scale if new_bid == True: dummy = 2 # print('**Bid', ts, unresp, resp_max, resp_deg, resp_c2, resp_c1) # update the case for bids, outages and CSV loads idx = int ((ts + dt) / period) % nloads bus = ppc['bus'] gen = ppc['gen'] branch = ppc['branch'] gencost = ppc['gencost'] csv_load = loads[idx,0] bus[4,2] = loads[idx,1] bus[8,2] = loads[idx,2] # process the generator and branch outages for row in ppc['UnitsOut']: if ts >= row[1] and ts <= row[2]: gen[row[0],7] = 0 else: gen[row[0],7] = 1 for row in ppc['BranchesOut']: if ts >= row[1] and ts <= row[2]: branch[row[0],10] = 0 else: branch[row[0],10] = 1 if resp_deg == 2: gencost[4][3] = 3 gencost[4][4] = -resp_c2 gencost[4][5] = resp_c1 elif resp_deg == 1: gencost[4][3] = 2 gencost[4][4] = resp_c1 gencost[4][5] = 0.0 else: gencost[4][3] = 1 gencost[4][4] = 999.0 gencost[4][5] = 0.0 gencost[4][6] = 0.0 if ts >= tnext_opf: # expecting to solve opf one dt before the market clearing period ends, so GridLAB-D has time to use it # for OPF, the FNCS bus load is CSV + Unresponsive estimate, with Responsive separately dispatchable bus = ppc['bus'] gen = ppc['gen'] bus[6,2] = csv_load for row in ppc['FNCS']: unresp = float(row[3]) newidx = int(row[0]) - 1 if unresp >= feeder_load: bus[newidx,2] += unresp else: bus[newidx,2] += feeder_load gen[4][9] = -resp_max res = pp.runopf(ppc, ppopt_market) if res['success'] == False: conv_accum = False opf_bus = deepcopy (res['bus']) opf_gen = deepcopy (res['gen']) lmp = opf_bus[6,13] resp = -1.0 * opf_gen[4,1] fncs.publish('LMP_B7', 0.001 * lmp) # publishing $/kwh # print (' OPF', ts, csv_load, '{:.3f}'.format(unresp), '{:.3f}'.format(resp), # '{:.3f}'.format(feeder_load), '{:.3f}'.format(opf_bus[6,2]), # '{:.3f}'.format(opf_gen[0,1]), '{:.3f}'.format(opf_gen[1,1]), '{:.3f}'.format(opf_gen[2,1]), # '{:.3f}'.format(opf_gen[3,1]), '{:.3f}'.format(opf_gen[4,1]), '{:.3f}'.format(lmp)) # if unit 2 (the normal swing bus) is dispatched at max, change the swing bus to 9 if opf_gen[1,1] >= 191.0: ppc['bus'][1,1] = 2 ppc['bus'][8,1] = 3 print (' SWING Bus 9') else: ppc['bus'][1,1] = 3 ppc['bus'][8,1] = 1 print (' SWING Bus 2') tnext_opf += period # always update the electrical quantities with a regular power flow bus = ppc['bus'] gen = ppc['gen'] bus[6,13] = lmp gen[0,1] = opf_gen[0, 1] gen[1,1] = opf_gen[1, 1] gen[2,1] = opf_gen[2, 1] gen[3,1] = opf_gen[3, 1] # during regular power flow, we use the actual CSV + feeder load, ignore dispatchable load and use actual bus[6,2] = csv_load + feeder_load gen[4,1] = 0 # opf_gen[4, 1] gen[4,9] = 0 rpf = pp.runpf(ppc, ppopt_regular) if rpf[0]['success'] == False: conv_accum = False bus = rpf[0]['bus'] gen = rpf[0]['gen'] Pload = bus[:,2].sum() Pgen = gen[:,1].sum() Ploss = Pgen - Pload # update the metrics n_accum += 1 loss_accum += Ploss for i in range (fncsBus.shape[0]): busnum = int(fncsBus[i,0]) busidx = busnum - 1 row = bus[busidx].tolist() # LMP_P, LMP_Q, PD, QD, Vang, Vmag, Vmax, Vmin: row[11] and row[12] are Vmax and Vmin constraints PD = row[2] + resp # the ERCOT version shows how to track scaled_resp separately for each FNCS bus Vpu = row[7] bus_accum[str(busnum)][0] += row[13]*0.001 bus_accum[str(busnum)][1] += row[14]*0.001 bus_accum[str(busnum)][2] += PD bus_accum[str(busnum)][3] += row[3] bus_accum[str(busnum)][4] += row[8] bus_accum[str(busnum)][5] += Vpu if Vpu > bus_accum[str(busnum)][6]: bus_accum[str(busnum)][6] = Vpu if Vpu < bus_accum[str(busnum)][7]: bus_accum[str(busnum)][7] = Vpu for i in range (gen.shape[0]): row = gen[i].tolist() busidx = int(row[0] - 1) # Pgen, Qgen, LMP_P (includes the responsive load as dispatched by OPF) gen_accum[str(i+1)][0] += row[1] gen_accum[str(i+1)][1] += row[2] gen_accum[str(i+1)][2] += float(opf_bus[busidx,13])*0.001 # write the metrics if ts >= tnext_metrics: sys_metrics[str(ts)] = {rootname:[loss_accum / n_accum,conv_accum]} bus_metrics[str(ts)] = {} for i in range (fncsBus.shape[0]): busnum = int(fncsBus[i,0]) busidx = busnum - 1 row = bus[busidx].tolist() met = bus_accum[str(busnum)] bus_metrics[str(ts)][str(busnum)] = [met[0]/n_accum, met[1]/n_accum, met[2]/n_accum, met[3]/n_accum, met[4]/n_accum, met[5]/n_accum, met[6], met[7]] bus_accum[str(busnum)] = [0,0,0,0,0,0,0,99999.0] gen_metrics[str(ts)] = {} for i in range (gen.shape[0]): met = gen_accum[str(i+1)] gen_metrics[str(ts)][str(i+1)] = [met[0]/n_accum, met[1]/n_accum, met[2]/n_accum] gen_accum[str(i+1)] = [0,0,0] tnext_metrics += period n_accum = 0 loss_accum = 0 conv_accum = True volts = 1000.0 * bus[6,7] * bus[6,9] / sqrt(3.0) # VLN for GridLAB-D fncs.publish('three_phase_voltage_B7', volts) # CSV file output print (ts, res['success'], '{:.3f}'.format(Pload), # Pload '{:.3f}'.format(csv_load), # P7 (csv) '{:.3f}'.format(unresp), # GLD Unresp '{:.3f}'.format(bus[6,2]), # P7 (rpf) '{:.3f}'.format(resp), # Resp (opf) '{:.3f}'.format(feeder_load), # GLD Pub new_bid, '{:.3f}'.format(gen[4,9]), # P7 Min '{:.3f}'.format(bus[6,7]), # V7 '{:.3f}'.format(bus[6,13]), # LMP_P7 '{:.3f}'.format(bus[6,14]), # LMP_Q7 '{:.2f}'.format(gen[0,1]), # Pgen1 '{:.2f}'.format(gen[1,1]), # Pgen2 '{:.2f}'.format(gen[2,1]), # Pgen3 '{:.2f}'.format(gen[3,1]), # Pgen4 '{:.2f}'.format(res['gen'][4, 1]), # Pdisp '{:.4f}'.format(resp_deg), # degree '{:.8f}'.format(ppc['gencost'][4, 4]), # c2 '{:.8f}'.format(ppc['gencost'][4, 5]), # c1 sep=',', file=op, flush=True) # request the next time step, if necessary if ts >= tmax: print ('breaking out at',ts,flush=True) break ts = fncs.time_request(min(ts + dt, tmax)) # =================================== print ('writing metrics', flush=True) print (json.dumps(sys_metrics), file=sys_mp, flush=True) print (json.dumps(bus_metrics), file=bus_mp, flush=True) print (json.dumps(gen_metrics), file=gen_mp, flush=True) print ('closing files', flush=True) bus_mp.close() gen_mp.close() sys_mp.close() op.close() print ('finalizing FNCS', flush=True) fncs.finalize() if sys.platform != 'win32': usage = resource.getrusage(resource.RUSAGE_SELF) RESOURCES = [ ('ru_utime', 'User time'), ('ru_stime', 'System time'), ('ru_maxrss', 'Max. Resident Set Size'), ('ru_ixrss', 'Shared Memory Size'), ('ru_idrss', 'Unshared Memory Size'), ('ru_isrss', 'Stack Size'), ('ru_inblock', 'Block inputs'), ('ru_oublock', 'Block outputs')] print('Resource usage:') for name, desc in RESOURCES: print(' {:<25} ({:<10}) = {}'.format(desc, name, getattr(usage, name)))
############################# Subscribing to Feeder Load from to GridLAB-D ############################################## for i in range(0, subkeys_count): sub = subid["m{}".format(i)] rload, iload = h.helicsInputGetComplex(sub) logger.info("Python Federate grantedtime = {}".format(grantedtime)) logger.info("Load value = {} kW".format(complex(rload, iload) / 1000)) #print(voltage_plot,real_demand) actual_demand = peak_demand * bus_profiles[x, :] ppc['bus'][:, 2] = actual_demand ppc['bus'][:, 3] = actual_demand * math.tan(math.acos(.85)) ppc['bus'][cosim_bus, 2] = rload * load_amplification_factor / 1000000 ppc['bus'][cosim_bus, 3] = iload * load_amplification_factor / 1000000 ppopt = ppoption(PF_ALG=1) print('PF TIme is {} and ACOPF time is {}'.format( time_pf[x], time_opf[k])) ############################ Running OPF For optimal power flow intervals ############################## if (time_pf[x] == time_opf[k]): results_opf = runopf(ppc, ppopt) if (results_opf['success']): ppc['bus'] = results_opf['bus'] ppc['gen'] = results_opf['gen'] if (k == 0): LMP_solved = results_opf['bus'][:, 13] else: LMP_solved = numpy.vstack(
print('bus #, Pd, Qd, Vm, LMP_P, LMP_Q, MU_VMAX, MU_VMIN') for row in bus: print(int(row[0]), row[2], row[3], row[7], row[13], row[14], row[15], row[16]) print('gen #, bus, Pg, Qg, MU_PMAX, MU_PMIN, MU_PMAX, MU_PMIN') idx = 1 for row in gen: print(idx, int(row[0]), row[1], row[2], row[21], row[22], row[23], row[24]) ++idx with warnings.catch_warnings(): ppc = ppcasefile() ppopt = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=1) gencost = ppc['gencost'] bus = ppc['bus'] gen = ppc['gen'] fncsBus = ppc['FNCS'] outage = ppc['UnitsOut'][0] bus[4, 2] = 97.124 # column 2, bus loads at 165000 from the TXT file bus[8, 2] = 134.89 # column 3 csv_load = 110.28 # column 1 # gen[outage[0],7] = 0 # unit 2 is out scale = float(fncsBus[0][2]) # mimic the FNCS messages coming in at 165000 for MW, prep and scale for OPF
ppc['branch'][-1, F_BUS] = 30 ppc['branch'][-1, T_BUS] = 33 ppc['branch'] = np.concatenate( (ppc['branch'], ppc['branch'][nbrch - 1:nbrch, :]), axis=0) ppc['branch'][-1, F_BUS] = 22 ppc['branch'][-1, T_BUS] = 32 # from pypower.case24_ieee_rts import case24_ieee_rts # ppc = case24_ieee_rts() #### ## LF by pypower (Newton-Raphson) using PYPOWER ### import pypower.api as pypow ppopt = pypow.ppoption(VERBOSE=0, OUT_ALL=0) #prevents results printing in each iteration start_time_LF = timeit.default_timer() results, success = pypow.runpf(ppc, ppopt=ppopt) #ppopt=ppopt time_LF = timeit.default_timer() - start_time_LF print("\n\t N-R converged in {0} s".format(time_LF)) if not success: print("\n powerflow did not converge") # #### # Direct load flow solution (a matrix back/fwd sweep) # #### start_time = timeit.default_timer()
'Ploss': { 'units': 'MW', 'index': 0 }, 'Converged': { 'units': 'true/false', 'index': 1 } } bus_metrics = {'Metadata': bus_meta, 'StartTime': StartTime} gen_metrics = {'Metadata': gen_meta, 'StartTime': StartTime} sys_metrics = {'Metadata': sys_meta, 'StartTime': StartTime} gencost = ppc['gencost'] fncsBus = ppc['FNCS'] ppopt = pp.ppoption( VERBOSE=0, OUT_ALL=0) # TODO - the PF_DC option doesn't seem to work loads = np.loadtxt('NonGLDLoad.txt', delimiter=',') outage = ppc['UnitsOut'][0] print('unit', outage[0], 'off from', outage[1], 'to', outage[2]) nloads = loads.shape[0] ts = 0 tnext = 0 op = open(rootname + '.csv', 'w') print('t[s],Converged,Pload,P7,V7,LMP_P7,LMP_Q7,Pgen1,Pgen2,Pgen3,Pgen4', file=op) fncs.initialize() # ts = -dt
def mainJAPowerFlow(baseMVAName, busName, genName, branchName, splitCharacter, outputBusName, outputBranchName, outputGenName, printOutput, optimal, areasName, genCostName): #Variables (by for testing) #baseMVAName = "baseMVA.txt" #busName = "bus.txt" #genName = "gen.txt" #branchName = "branch.txt" #splitCharacter = ' ' #outputBusName = "outputBus.txt" #outputBranchName = "outputBranch.txt" #outputBranchName = "outputGen.txt" #printOutput = 0 #printOutput = 0 or 1, 0 for no stdout printed output, 1 if it is wanted. Note that both still output to the text files. #optimal = 0 #optimal = 0 or 1, 0 for power flow, 1 for optimal power flow. NOTE: All following inputs are only used in optimal power flow, OPF, analysis (optimal = 1), but some values are still required as inputs, even if they are not used in the event of PF (optimal = 0). #areasName = "areas.txt" #genCostName = "genCost.txt" #Assign ppc ppc = readText(baseMVAName, busName, genName, branchName, splitCharacter, optimal, areasName, genCostName) #ppc = casetest() #Set pf test type #ppopt = ppoption(PF_ALG=1) #Includes printing output (of standard pf) #ppopt = ppoption(OUT_ALL=0, VERBOSE=0) #These options prevent printing output #ppopt = ppoption(PF_ALG=1, OUT_ALL=0, VERBOSE=0) if (printOutput == 1): ppopt = ppoption(OUT_ALL=1, VERBOSE=1) elif (printOutput == 0): ppopt = ppoption(OUT_ALL=0, VERBOSE=0) else: print( "printOutput must be 0 or 1, 0 for no stdout printed output, and 1 if that is desired. Both still output to text files." ) #Run pf or opf test if (optimal == 0): r = runpf(ppc, ppopt) elif (optimal == 1): r = runopf(ppc, ppopt) else: print("optimal must be 0 or 1, 0 for pf and 1 for opf.") #Now clear the output files (method of writing to them might be altered, so doing this is to be sure open(outputBusName, 'w').close() open(outputBranchName, 'w').close() open(outputGenName, 'w').close() #For Optimal Power Flow if (optimal == 1): #Establish lengths busCount = len(r['bus']) branchCount = len(r['branch']) genCount = len(r['gen']) #Find Generator Per Bus Output busGenP = numpy.zeros(busCount, dtype=numpy.float) busGenQ = numpy.zeros(busCount, dtype=numpy.float) f = open(outputGenName, 'w') i = 0 while (i < genCount): #For Gen Output f.write( str(i + 1) + splitCharacter + str(r['gen'][i][1]) + splitCharacter + str(r['gen'][i][2]) + '\n') #For Bus Output busGenP[int(r['gen'][i][0])] += r['gen'][i][1] busGenQ[int(r['gen'][i][0])] += r['gen'][i][2] i += 1 f.close() #Print Bus Output f = open(outputBusName, 'w') i = 0 while (i < busCount): f.write( str(i + 1) + splitCharacter + str(r['bus'][i][7]) + splitCharacter + str(r['bus'][i][8]) + splitCharacter + str(busGenP[i]) + splitCharacter + str(busGenQ[i]) + splitCharacter + str(r['bus'][i][2]) + splitCharacter + str(r['bus'][i][3]) + '\n') i += 1 f.close() #Print Branch Output f = open(outputBranchName, 'w') i = 0 dic = {} while (i < branchCount): f.write( str(i + 1) + splitCharacter + str(absDiff(r['branch'][i][15], r['branch'][i][13])) + splitCharacter + str(absDiff(r['branch'][i][16], r['branch'][i][14])) + '\n') dic[i] = [ str(absDiff(r['branch'][i][15], r['branch'][i][13])), str(absDiff(r['branch'][i][16], r['branch'][i][14])) ] i += 1 f.close() with open( 'C:\\Users\\LONG01\\TOMCAT\\webapps\\ROOT\OntoEN\\outputOPF.json', 'w') as fp: json.dump(dic, fp) #For Standard Power Flow elif (optimal == 0): #Establish lengths busCount = len(r[0]['bus']) branchCount = len(r[0]['branch']) #print(branchCount) genCount = len(r[0]['gen']) #Find Generator Per Bus Output busGenP = numpy.zeros(busCount, dtype=numpy.float) busGenQ = numpy.zeros(busCount, dtype=numpy.float) f = open(outputGenName, 'w') i = 0 while (i < genCount): #For Gen Output f.write( str(i + 1) + splitCharacter + str(r[0]['gen'][i][1]) + splitCharacter + str(r[0]['gen'][i][2]) + '\n') #For Bus Output busGenP[int(r[0]['gen'][i][0])] += r[0]['gen'][i][1] busGenQ[int(r[0]['gen'][i][0])] += r[0]['gen'][i][2] i += 1 f.close() #Print Bus Output f = open(outputBusName, 'w') i = 0 while (i < busCount): f.write( str(i + 1) + splitCharacter + str(r[0]['bus'][i][7]) + splitCharacter + str(r[0]['bus'][i][8]) + splitCharacter + str(busGenP[i]) + splitCharacter + str(busGenQ[i]) + splitCharacter + str(r[0]['bus'][i][2]) + splitCharacter + str(r[0]['bus'][i][3]) + '\n') i += 1 f.close() #Print Branch Output f = open(outputBranchName, 'w') i = 0 while (i < branchCount): #P, Q and S (average) PAve = (r[0]['branch'][i][15] + r[0]['branch'][i][13]) / 2.0 QAve = (r[0]['branch'][i][14] + r[0]['branch'][i][16]) / 2.0 SAve = numpy.sqrt(((PAve * PAve) + (QAve * QAve))) #Print P loss, Q loss, aveP, aveQ and aveS. f.write( str(i + 1) + splitCharacter + str(absDiff(r[0]['branch'][i][15], r[0]['branch'][i][13])) + splitCharacter + str(absDiff(r[0]['branch'][i][16], r[0]['branch'][i][14])) + splitCharacter + str(PAve) + splitCharacter + str(QAve) + splitCharacter + str(SAve) + '\n') i += 1 f.close() else: print("optimal must be 0 or 1, 0 for pf and 1 for opf.")
""" Created on Wed Feb 24 15:13:38 2016 @author: saf537 """ import case14_mod import pandas as pd import pypower.api as pypo import numpy as np load_shapes = pd.read_csv('loadShapes1.csv') sample = 100*load_shapes.iloc[0][load_shapes.columns[9:]] ppc0 = case14_mod.case14_mod(busN = 1,dlt = 0, op_change=1) # trivial case: original solutin ppopt0 = pypo.ppoption(PF_ALG=2,VERBOSE=0, OUT_ALL=0) r0 = pypo.runpf(ppc0, ppopt0) n_trs = sum(r0[0]['bus'][:,1] == 2) n_bldgs = sum(r0[0]['bus'][:,1] == 1) transfs = r0[0]['bus'][:,0][r0[0]['bus'][:,1]==2] bdgs = r0[0]['bus'][:,0][r0[0]['bus'][:,1]==1] tm_max = len(sample) # bus 8, power after solution TS = np.empty((n_bldgs,n_trs,tm_max)) initial_loads_vec = r0[0]['bus'][:,2] cont = 0 for i in bdgs: tmp = 0 ini_load = initial_loads_vec[i-1] for j in transfs:
dlt_vec = [0.05, -0.05, 0.10, -0.10, 0.50, -0.50] ppc0 = case14_mod.case14_mod(busN = 1,dlt = 0, op_change=1) # trivial case: original solutin #ppopt0 = pypo.ppoption(PF_ALG=2, VERBOSE=0, # OUT_ALL = False, # OUT_ALL_LIM = False, # OUT_AREA_SUM = False, # OUT_BRANCH = False, # OUT_BUS = False, # OUT_GEN = False, # OUT_LINE_LIM = False, # OUT_PG_LIM = False, # OUT_QG_LIM = False, # OUT_SYS_SUM = False, # OUT_V_LIM = False) # Careful: have to use Newton Method!!! ppopt0 = pypo.ppoption(PF_ALG=2, VERBOSE=0, OUT_ALL=0) # Careful: have to use Newton Method!!! r0 = pypo.runpf(ppc0, ppopt0) m1 = r0[0]['gen'][:,2][1:] p0 = [m1 for i in range(0,8)] mtr = zeros([8,4,len(dlt_vec)]) j = 1 for j in range(0,len(dlt_vec)): tmp = 0 for i in range(0,13): if r0[0]['bus'][i,1] == 1: ppc = case14_mod.case14_mod(busN = i,dlt = dlt_vec[j], op_change=1) ppopt = pypo.ppoption(PF_ALG=2, VERBOSE=0, OUT_ALL=0) # Careful: have to use Newton Method!!! r = pypo.runpf(ppc, ppopt) #plt.plot(r[0]['bus'][:,2]) pwr = r[0]['gen'][:,2][1:] # voltage 7, type 2
def parse_options(args, usage, opf=False): """Parse command line options. @param opf: Include OPF options? """ v = ppver('all') parser = OptionParser( usage="""usage: %%prog [options] [casedata] %s If 'casedata' is provided it specifies the name of the input data file containing the case data.""" % usage, version='PYPOWER (%%prog) Version %s, %s' % (v["Version"], v["Date"]) ) parser.add_option("-t", "--test", action="store_true", dest="test", default=False, help="run tests and exit") parser.add_option("-c", "--testcase", default='case9', choices=list(CASES.keys()), help="built-in test case, choose from: %s" % str( list(CASES.keys()))[1:-1]) parser.add_option("-o", "--outfile", dest='fname', default='', type='string', help="""pretty printed output will be appended to a file with the name specified. Defaults to stdout.""") parser.add_option("-s", "--solvedcase", default='', type='string', help="""the solved case will be written to a case file with the specified name in PYPOWER format. If solvedcase ends with '.mat' the case is saves as a MAT-file otherwise it saves it as a Python file.""") ppopt = ppoption() if opf: opf_options = OptionGroup(parser, 'OPF Options') pdipm_options = OptionGroup(parser, 'PDIPM Options') opf_options.add_option("-u", "--uopf", action="store_true", help="""runs an optimal power flow with the unit-decommitment heuristic""") opf_options.add_option("-r", "--w_res", action="store_true", help="""runs an optimal power flow with fixed zonal reserves""") add_options(opf_options, OPF_OPTIONS, ppopt) add_options(pdipm_options, PDIPM_OPTIONS, ppopt) parser.add_option_group(opf_options) parser.add_option_group(pdipm_options) else: pf_options = OptionGroup(parser, 'Power Flow Options') add_options(pf_options, PF_OPTIONS, ppopt) parser.add_option_group(pf_options) output_options = OptionGroup(parser, 'Output Options') add_options(output_options, OUTPUT_OPTIONS, ppopt) parser.add_option_group(output_options) options, args = parser.parse_args(args) # casedata, fname, solvedcase = case9(), '', '' # defaults nargs = len(args) if nargs > 1: stderr.write('Too many arguments') parser.print_help() sys.exit(2) elif nargs == 1: casedata = args[0] else: try: casedata = CASES[options.testcase]() except KeyError: stderr.write("Invalid case choice: %r (choose from %s)\n" % \ (options.testcase, list(CASES.keys()))) sys.exit(2) return options, casedata, ppopt, options.fname, options.solvedcase
def mainJAPowerFlow(baseMVAName, busName, genName, branchName, splitCharacter, outputBusName, outputBranchName, outputGenName, optimal, printOutput, areasName, genCostName): #Variables (by for testing) #baseMVAName = "baseMVA.txt" #busName = "bus.txt" #genName = "gen.txt" #branchName = "branch.txt" #splitCharacter = ' ' #outputBusName = "outputBus.txt" #outputBranchName = "outputBranch.txt" #outputBranchName = "outputGen.txt" #optimal = 0 #optimal = 0 or 1, 0 for power flow, 1 for optimal power flow. #printOutput = 0 #printOutput = 0 or 1, 0 for no stdout printed output, 1 if it is wanted. Note that both still output to the text files. #areasName = "areas.txt" #genCostName = "genCost.txt" #Assign ppc ppc = readText(baseMVAName, busName, genName, branchName, splitCharacter, optimal, areasName, genCostName) #ppc = casetest() #Set pf test type #ppopt = ppoption(PF_ALG=1) #Includes printing output (of standard pf) #ppopt = ppoption(OUT_ALL=0, VERBOSE=0) #These options prevent printing output #ppopt = ppoption(PF_ALG=1, OUT_ALL=0, VERBOSE=0) if (printOutput == 1): ppopt = ppoption(OUT_ALL=1, VERBOSE=1) elif (printOutput == 0): ppopt = ppoption(OUT_ALL=0, VERBOSE=0) else: print( "printOutput must be 0 or 1, 0 for no stdout printed output, and 1 if that is desired. Both still output to text files." ) #Run pf or opf test if (optimal == 0): r = runpf(ppc, ppopt) elif (optimal == 1): r = runopf(ppc, ppopt) else: print("optimal must be 0 or 1, 0 for pf and 1 for opf.") #Now clear the output files (method of writing to them might be altered, so doing this is to be sure open(outputBusName, 'w').close() open(outputBranchName, 'w').close() open(outputGenName, 'w').close() #For Optimal Power Flow if (optimal == 1): #Establish lengths busCount = len(r['bus']) branchCount = len(r['branch']) genCount = len(r['gen']) #Find Generator Per Bus Output busGenP = numpy.zeros(busCount, dtype=numpy.float) busGenQ = numpy.zeros(busCount, dtype=numpy.float) f = open(outputGenName, 'w') i = 0 while (i < genCount): #For Gen Output f.write( str(i + 1) + splitCharacter + str(r['gen'][i][1]) + splitCharacter + str(r['gen'][i][2]) + '\n') #For Bus Output busGenP[int(r['gen'][i][0])] += r['gen'][i][1] busGenQ[int(r['gen'][i][0])] += r['gen'][i][2] i += 1 f.close() #Print Bus Output f = open(outputBusName, 'w') i = 0 while (i < busCount): f.write( str(i + 1) + splitCharacter + str(r['bus'][i][7]) + splitCharacter + str(r['bus'][i][8]) + splitCharacter + str(busGenP[i]) + splitCharacter + str(busGenQ[i]) + splitCharacter + str(r['bus'][i][2]) + splitCharacter + str(r['bus'][i][3]) + '\n') i += 1 f.close() #Print Branch Output f = open(outputBranchName, 'w') i = 0 while (i < branchCount): f.write( str(i + 1) + splitCharacter + str(absDiff(r['branch'][i][15], r['branch'][i][13])) + splitCharacter + str(absDiff(r['branch'][i][16], r['branch'][i][14])) + '\n') i += 1 f.close() #For Standard Power Flow elif (optimal == 0): #Establish lengths busCount = len(r[0]['bus']) branchCount = len(r[0]['branch']) #print(branchCount) genCount = len(r[0]['gen']) #Find Generator Per Bus Output busGenP = numpy.zeros(busCount, dtype=numpy.float) busGenQ = numpy.zeros(busCount, dtype=numpy.float) f = open(outputGenName, 'w') i = 0 while (i < genCount): #For Gen Output f.write( str(i + 1) + splitCharacter + str(r[0]['gen'][i][1]) + splitCharacter + str(r[0]['gen'][i][2]) + '\n') #For Bus Output busGenP[int(r[0]['gen'][i][0])] += r[0]['gen'][i][1] busGenQ[int(r[0]['gen'][i][0])] += r[0]['gen'][i][2] i += 1 f.close() #Print Bus Output f = open(outputBusName, 'w') i = 0 while (i < busCount): f.write( str(i + 1) + splitCharacter + str(r[0]['bus'][i][7]) + splitCharacter + str(r[0]['bus'][i][8]) + splitCharacter + str(busGenP[i]) + splitCharacter + str(busGenQ[i]) + splitCharacter + str(r[0]['bus'][i][2]) + splitCharacter + str(r[0]['bus'][i][3]) + '\n') i += 1 f.close() #Print Branch Output f = open(outputBranchName, 'w') i = 0 while (i < branchCount): f.write( str(i + 1) + splitCharacter + str(absDiff(r[0]['branch'][i][15], r[0]['branch'][i][13])) + splitCharacter + str(absDiff(r[0]['branch'][i][16], r[0]['branch'][i][14])) + '\n') i += 1 f.close() else: print("optimal must be 0 or 1, 0 for pf and 1 for opf.")
def _get_param(self): # delect the disturbances not defined in the set_disturb, and renumber the new disturbance set. for d_type in {1, 2, 3, 4}: i_d_all = list() for i_d in range(len(self.casedata['disturbance'][d_type])): if (d_type, self.casedata['disturbance'][d_type][i_d, 0] ) in self.set_disturb: i_d_all.append(i_d) self.casedata['disturbance'][d_type] = self.casedata[ 'disturbance'][d_type][i_d_all, :] for i_d in range(len(self.casedata['disturbance'][d_type])): self.casedata['disturbance'][d_type][i_d, 0] = i_d + 1 if len(self.casedata['disturbance'][d_type]) == 0: del self.casedata['disturbance'][d_type] # parameters if len(self.casedata['bus']) >= 200 or len(self.casedata['bus']) == 59: opt = ppoption(PF_TOL=1e-12, PF_MAX_IT=20) else: opt = ppoption(PF_TOL=1e-13, PF_MAX_IT=20) s_pf = runpf(self.casedata, opt) pcc_y = ext2int(self.casedata) Ybus = makeYbus(pcc_y["baseMVA"], pcc_y["bus"], pcc_y["branch"])[0].toarray() n_bus = len(Ybus) B_0 = np.imag(Ybus) for i in range(len(B_0)): B_0[i, i] = 0 pg_0 = np.zeros(n_bus) pg_0[(s_pf[0]['gen'][:, 0] - 1).astype(int)] = s_pf[0]['gen'][:, 1] i_gen = self.casedata['gen'][:, 0].astype(int).tolist() i_non_0 = (np.where(self.casedata['bus'][:, 2] == 0)[0] + 1).tolist() i_non = list(set(i_non_0).difference(set(i_gen))) i_load_0 = list( set(self.casedata['bus'][:, 0].astype(int).tolist()).difference( set(i_gen))) i_load = list(set(i_load_0).difference(set(i_non))) self.Ybus = Ybus self.n_bus = n_bus self.B_0 = B_0 self.v_0 = s_pf[0]['bus'][:, 7] self.theta_0 = np.radians(s_pf[0]['bus'][:, 8]) self.pl_0 = s_pf[0]['bus'][:, 2] / 100.0 self.pg_0 = pg_0 / 100.0 self.w_0 = np.zeros(self.n_bus) self.i_gen = i_gen self.i_non = i_non self.i_load = i_load self.i_gl = i_gen + i_load self.i_all = self.casedata['bus'][:, 0].astype(int).tolist() self.theta_gl_0 = self.theta_0[(np.array(self.i_gl) - 1).tolist()] # initial values and bounds of optimization variables self.m_0, self.m_l, self.m_u = dict(), dict(), dict() self.d_0, self.d_l, self.d_u = dict(), dict(), dict() self.M = self.casedata['bus'][:, 13].tolist() self.D = self.casedata['bus'][:, 14].tolist() for i in self.i_gen: i_gc = np.where(self.casedata['gencontrol'][:, 0] == i)[0] i_bus = np.where(self.casedata['bus'][:, 0] == i)[0][0] self.m_0[i] = self.M[i_bus] self.m_l[i] = self.casedata['gencontrol'][i_gc, 2][0] self.m_u[i] = self.casedata['gencontrol'][i_gc, 3][0] self.d_0[i] = self.D[i_bus] self.d_l[i] = self.casedata['gencontrol'][i_gc, 4][0] self.d_u[i] = self.casedata['gencontrol'][i_gc, 5][0] # set of index for each kind of branch, used for computing the objective function self.ind_branch = list( ) # index set [(ind_bus_from, ind_bus_to)] of all branch for i_b in self.casedata['branch'][:, [0, 1]]: self.ind_branch.append((int(i_b[0]), int(i_b[1]))) set_k_i = list() # list of (k,i) of all disturbances and time elements for k0 in self.casedata['disturbance'].keys(): if k0 != 9: for k1 in self.casedata['disturbance'][k0][:, 0]: for i in range( 1, self.casedata['param_disc']['time_ele'][k0] + 1): set_k_i.append(((int(k0), int(k1)), i)) self.set_k_i = set_k_i
def mainJAPowerFlow(baseMVAName, busName, genName, branchName, splitCharacter, outputBusName, outputBranchName, outputGenName, printOutput, optimal, areasName, genCostName): # Variables (by for testing) # baseMVAName = "baseMVA.txt" # busName = "bus.txt" # genName = "gen.txt" # branchName = "branch.txt" # splitCharacter = ' ' # outputBusName = "outputBus.txt" # outputBranchName = "outputBranch.txt" # outputBranchName = "outputGen.txt" # printOutput = 0 ##### printOutput = 0 or 1, 0 for no stdout printed output, 1 if it is wanted. ##### Note that both still output to the text files. # optimal = 0 ##### optimal = 0 or 1, 0 for power flow, 1 for optimal power flow. ##### NOTE: All following inputs are only used in optimal power flow, OPF, analysis (optimal = 1), ##### but some values are still required as inputs, even if they are not used in the event of PF (optimal = 0). # areasName = "areas.txt" # genCostName = "genCost.txt" # Assign ppc ppc = readText(baseMVAName, busName, genName, branchName, splitCharacter, optimal, areasName, genCostName) #ppc = casetest() # Set pf test type # ppopt = ppoption(PF_ALG=1) ---> Power Flow algorithm: 1- NR Method # ppopt = ppoption(OUT_ALL=0, VERBOSE=0) ---> These options prevent printing output # ppopt = ppoption(PF_ALG=1, OUT_ALL=0, VERBOSE=0) if (printOutput == 1): ppopt = ppoption(OUT_ALL=1, VERBOSE=1) elif (printOutput == 0): ppopt = ppoption(OUT_ALL=0, VERBOSE=0) else: print( "printOutput must be 0 or 1, 0 for no stdout printed output, and 1 if that is desired. Both still output to text files." ) # (A) --pf_alg = PF_ALG # power flow algorithm : # 1 - Newton’s method, # 2 - FastDecoupled (XB version), # 3 - Fast-Decoupled (BX # version), # 4 - Gauss Seidel # [default: 1] # (B) --verbose = VERBOSE # amount of progress info printed: # 0 - print no progress info, # 1 - print a little progress info, # 2 - print a lot of progress info, # 3 - print all progress info # [default: 1] # (C) --out_all = OUT_ALL # controls printing of results: # -1 - individual flags control what prints, # 0 - don’t print anything # (overrides individual flags, except OUT_RAW), # 1 - print everything (overrides individual flags, except OUT_RAW) # [default: -1] # Run pf or opf test if (optimal == 0): r = runpf(ppc, ppopt) elif (optimal == 1): r = runopf(ppc, ppopt) else: print("optimal must be 0 or 1, 0 for pf and 1 for opf.") # Check if voltage constraints are met? # Check if solution converged? if (optimal == 1): genCount = len(r['gen']) #check no. of generators = 16 busCount = len(r['bus']) #check no. of buses = 15 branchCount = len(r['branch']) #check no. of branches = 25 print("\nNo. of gen= ", genCount) print("\nbus= ", busCount) print("\nbranch=", branchCount) busGenP = numpy.zeros( genCount, dtype=numpy.float ) #create a zero column vector (16x1) for P generation busLoadP = numpy.zeros( busCount, dtype=numpy.float) #create a zero column vector (15x1) for P load branchLoss = numpy.zeros( branchCount, dtype=numpy.float ) #create a zero column vector (25x1) for branch losses i = 0 while (i < genCount): #busGenP[int(r['gen'][i][1])] += r['gen'][i][1] busGenP[i] += r['gen'][i][1] i += 1 j = 0 while (j < busCount): busLoadP[j] += r['bus'][j][2] j += 1 k = 0 while (k < branchCount): branchLoss[k] += absDiff(r['branch'][k][15], r['branch'][k][13]) k += 1 # print("\nReal power generated= \n",busGenP) # print("\nReal power demand= \n", busLoadP) # print ("\nBranch Losses= \n", branchLoss) sumGen = round(busGenP.sum(), 2) # round off up to 2 decimal points. sumLoad = round(busLoadP.sum(), 2) sumLoss = round(branchLoss.sum(), 2) print("\n") print("\nTotal Real Power Generation= ", sumGen) print("\nTotal Real Power Load= ", sumLoad) print("\nTotal Real Power Losses= ", sumLoss) print("\n") # Clears the output files (method of writing to them might be altered, so doing this is to be sure open(outputBusName, 'w').close() open(outputBranchName, 'w').close() open(outputGenName, 'w').close() # For Optimal Power Flow #Establish lengths busCount = len(r['bus']) branchCount = len(r['branch']) genCount = len(r['gen']) #Find Generator Per Bus Output busGenP = numpy.zeros(busCount, dtype=numpy.float) busGenQ = numpy.zeros(busCount, dtype=numpy.float) f = open(outputGenName, 'w') i = 0 while (i < genCount): #Print Gen Output f.write( str(i + 1) + splitCharacter + str(r['gen'][i][1]) + splitCharacter + str(r['gen'][i][2]) + '\n') #For Bus Output --> assign values for busGenP and busGenQ busGenP[int(r['gen'][i][0])] += r['gen'][i][1] busGenQ[int(r['gen'][i][0])] += r['gen'][i][2] i += 1 f.close() #Print Bus Output f = open(outputBusName, 'w') i = 0 while (i < busCount): f.write( str(i + 1) + splitCharacter + str(r['bus'][i][7]) + splitCharacter + str(r['bus'][i][8]) + splitCharacter + str(busGenP[i]) + splitCharacter + str(busGenQ[i]) + splitCharacter + str(r['bus'][i][2]) + splitCharacter + str(r['bus'][i][3]) + '\n') i += 1 f.close() #Print Branch Output f = open(outputBranchName, 'w') i = 0 while (i < branchCount): #P, Q and S (average) PAve = (r['branch'][i][15] + r['branch'][i][13]) / 2.0 QAve = (r['branch'][i][14] + r['branch'][i][16]) / 2.0 SAve = numpy.sqrt(((PAve * PAve) + (QAve * QAve))) f.write( str(i + 1) + splitCharacter + str(absDiff(r['branch'][i][15], r['branch'][i][13])) + splitCharacter + str(absDiff(r['branch'][i][16], r['branch'][i][14])) + splitCharacter + str(PAve) + splitCharacter + str(QAve) + splitCharacter + str(SAve) + '\n') i += 1 f.close()
def test_pypower_case(): #ppopt is a dictionary with the details of the optimization routine to run ppopt = ppoption(PF_ALG=2) #choose DC or AC ppopt["PF_DC"] = False #ppc is a dictionary with details about the network, including baseMVA, branches and generators ppc = case() results,success = runpf(ppc, ppopt) #store results in a DataFrame for easy access results_df = {} #branches columns = 'bus0, bus1, r, x, b, rateA, rateB, rateC, ratio, angle, status, angmin, angmax, p0, q0, p1, q1'.split(", ") results_df['branch'] = pd.DataFrame(data=results["branch"],columns=columns) #buses columns = ["bus","type","Pd","Qd","Gs","Bs","area","v_mag_pu","v_ang","v_nom","zone","Vmax","Vmin"] results_df['bus'] = pd.DataFrame(data=results["bus"],columns=columns,index=results["bus"][:,0]) #generators columns = "bus, p, q, q_max, q_min, Vg, mBase, status, p_max, p_min, Pc1, Pc2, Qc1min, Qc1max, Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30, ramp_q, apf".split(", ") results_df['gen'] = pd.DataFrame(data=results["gen"],columns=columns) #now compute in PyPSA network = pypsa.Network() network.import_from_pypower_ppc(ppc) #PYPOWER uses PI model for transformers, whereas PyPSA defaults to #T since version 0.8.0 network.transformers.model = "pi" network.pf() #compare branch flows for c in network.iterate_components(pypsa.components.passive_branch_components): for si in ["p0","p1","q0","q1"]: si_pypsa = getattr(c.pnl,si).loc["now"].values si_pypower = results_df['branch'][si][c.df.original_index].values np.testing.assert_array_almost_equal(si_pypsa,si_pypower) #compare generator dispatch for s in ["p","q"]: s_pypsa = getattr(network.generators_t,s).loc["now"].values s_pypower = results_df["gen"][s].values np.testing.assert_array_almost_equal(s_pypsa,s_pypower) #compare voltages v_mag_pypsa = network.buses_t.v_mag_pu.loc["now"] v_mag_pypower = results_df["bus"]["v_mag_pu"] np.testing.assert_array_almost_equal(v_mag_pypsa,v_mag_pypower) v_ang_pypsa = network.buses_t.v_ang.loc["now"] pypower_slack_angle = results_df["bus"]["v_ang"][results_df["bus"]["type"] == 3].values[0] v_ang_pypower = (results_df["bus"]["v_ang"] - pypower_slack_angle)*np.pi/180. np.testing.assert_array_almost_equal(v_ang_pypsa,v_ang_pypower)
def test_pypower_case(): #ppopt is a dictionary with the details of the optimization routine to run ppopt = ppoption(PF_ALG=2) #choose DC or AC ppopt["PF_DC"] = False #ppc is a dictionary with details about the network, including baseMVA, branches and generators ppc = case() results, success = runpf(ppc, ppopt) #store results in a DataFrame for easy access results_df = {} #branches columns = 'bus0, bus1, r, x, b, rateA, rateB, rateC, ratio, angle, status, angmin, angmax, p0, q0, p1, q1'.split( ", ") results_df['branch'] = pd.DataFrame(data=results["branch"], columns=columns) #buses columns = [ "bus", "type", "Pd", "Qd", "Gs", "Bs", "area", "v_mag_pu", "v_ang", "v_nom", "zone", "Vmax", "Vmin" ] results_df['bus'] = pd.DataFrame(data=results["bus"], columns=columns, index=results["bus"][:, 0]) #generators columns = "bus, p, q, q_max, q_min, Vg, mBase, status, p_max, p_min, Pc1, Pc2, Qc1min, Qc1max, Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30, ramp_q, apf".split( ", ") results_df['gen'] = pd.DataFrame(data=results["gen"], columns=columns) #now compute in PyPSA network = pypsa.Network() network.import_from_pypower_ppc(ppc) #PYPOWER uses PI model for transformers, whereas PyPSA defaults to #T since version 0.8.0 network.transformers.model = "pi" network.pf() #compare branch flows for c in network.iterate_components(network.passive_branch_components): for si in ["p0", "p1", "q0", "q1"]: si_pypsa = getattr(c.pnl, si).loc["now"].values si_pypower = results_df['branch'][si][c.df.original_index].values equal(si_pypsa, si_pypower) #compare generator dispatch for s in ["p", "q"]: s_pypsa = getattr(network.generators_t, s).loc["now"].values s_pypower = results_df["gen"][s].values equal(s_pypsa, s_pypower) #compare voltages v_mag_pypsa = network.buses_t.v_mag_pu.loc["now"] v_mag_pypower = results_df["bus"]["v_mag_pu"] equal(v_mag_pypsa, v_mag_pypower) v_ang_pypsa = network.buses_t.v_ang.loc["now"] pypower_slack_angle = results_df["bus"]["v_ang"][results_df["bus"]["type"] == 3].values[0] v_ang_pypower = (results_df["bus"]["v_ang"] - pypower_slack_angle) * np.pi / 180. equal(v_ang_pypsa, v_ang_pypower)
def solveOpf(caseName, config): bxObj = ptbx.InitCases(caseName) sysN, sysopt = opf_args.opf_args2(bxObj.System) sysopt = pyp.ppoption(sysopt, VERBOSE=3) results = pyp.runopf(bxObj.System, sysopt) print("Success")
def parse_options(args, usage, opf=False): """Parse command line options. @param opf: Include OPF options? """ v = ppver('all') parser = OptionParser( usage="""usage: %%prog [options] [casedata] %s If 'casedata' is provided it specifies the name of the input data file containing the case data.""" % usage, version='PYPOWER (%%prog) Version %s, %s' % (v["Version"], v["Date"]) ) parser.add_option("-t", "--test", action="store_true", dest="test", default=False, help="run tests and exit") parser.add_option("-c", "--testcase", default='case9', choices=CASES.keys(), help="built-in test case, choose from: %s" % str(CASES.keys())[1:-1]) parser.add_option("-o", "--outfile", dest='fname', default='', type='string', help="""pretty printed output will be appended to a file with the name specified. Defaults to stdout.""") parser.add_option("-s", "--solvedcase", default='', type='string', help="""the solved case will be written to a case file with the specified name in PYPOWER format. If solvedcase ends with '.mat' the case is saves as a MAT-file otherwise it saves it as a Python file.""") ppopt = ppoption() if opf: opf_options = OptionGroup(parser, 'OPF Options') pdipm_options = OptionGroup(parser, 'PDIPM Options') opf_options.add_option("-u", "--uopf", action="store_true", help="""runs an optimal power flow with the unit-decommitment heuristic""") opf_options.add_option("-r", "--w_res", action="store_true", help="""runs an optimal power flow with fixed zonal reserves""") add_options(opf_options, OPF_OPTIONS, ppopt) add_options(pdipm_options, PDIPM_OPTIONS, ppopt) parser.add_option_group(opf_options) parser.add_option_group(pdipm_options) else: pf_options = OptionGroup(parser, 'Power Flow Options') add_options(pf_options, PF_OPTIONS, ppopt) parser.add_option_group(pf_options) output_options = OptionGroup(parser, 'Output Options') add_options(output_options, OUTPUT_OPTIONS, ppopt) parser.add_option_group(output_options) options, args = parser.parse_args(args) # casedata, fname, solvedcase = case9(), '', '' # defaults nargs = len(args) if nargs > 1: stderr.write('Too many arguments') parser.print_help() sys.exit(2) elif nargs == 1: casedata = args[0] else: try: casedata = CASES[options.testcase]() except KeyError: stderr.write("Invalid case choice: %r (choose from %s)\n" % \ (options.testcase, CASES.keys())) sys.exit(2) return options, casedata, ppopt, options.fname, options.solvedcase
def main_loop(): if len(sys.argv) == 2: rootname = sys.argv[1] else: print('usage: python fncsPYPOWER.py rootname') sys.exit() ppc = ppcasefile() StartTime = ppc['StartTime'] tmax = int(ppc['Tmax']) period = int(ppc['Period']) dt = int(ppc['dt']) make_dictionary(ppc, rootname) bus_mp = open("bus_" + rootname + "_metrics.json", "w") gen_mp = open("gen_" + rootname + "_metrics.json", "w") sys_mp = open("sys_" + rootname + "_metrics.json", "w") bus_meta = { 'LMP_P': { 'units': 'USD/kwh', 'index': 0 }, 'LMP_Q': { 'units': 'USD/kvarh', 'index': 1 }, 'PD': { 'units': 'MW', 'index': 2 }, 'QD': { 'units': 'MVAR', 'index': 3 }, 'Vang': { 'units': 'deg', 'index': 4 }, 'Vmag': { 'units': 'pu', 'index': 5 }, 'Vmax': { 'units': 'pu', 'index': 6 }, 'Vmin': { 'units': 'pu', 'index': 7 } } gen_meta = { 'Pgen': { 'units': 'MW', 'index': 0 }, 'Qgen': { 'units': 'MVAR', 'index': 1 }, 'LMP_P': { 'units': 'USD/kwh', 'index': 2 } } sys_meta = { 'Ploss': { 'units': 'MW', 'index': 0 }, 'Converged': { 'units': 'true/false', 'index': 1 } } bus_metrics = {'Metadata': bus_meta, 'StartTime': StartTime} gen_metrics = {'Metadata': gen_meta, 'StartTime': StartTime} sys_metrics = {'Metadata': sys_meta, 'StartTime': StartTime} gencost = ppc['gencost'] fncsBus = ppc['FNCS'] ppopt = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=1) loads = np.loadtxt('NonGLDLoad.txt', delimiter=',') for row in ppc['UnitsOut']: print('unit ', row[0], 'off from', row[1], 'to', row[2], flush=True) for row in ppc['BranchesOut']: print('branch', row[0], 'out from', row[1], 'to', row[2], flush=True) nloads = loads.shape[0] ts = 0 tnext_opf = -dt op = open(rootname + '.csv', 'w') print( 't[s],Converged,Pload,P7 (csv), GLD Unresp, P7 (opf), Resp (opf), GLD Pub, BID?, P7 Min, V7,LMP_P7,LMP_Q7,Pgen1,Pgen2,Pgen3,Pgen4,Pdisp, gencost2, gencost1, gencost0', file=op, flush=True) # print ('t[s], ppc-Pd5, ppc-Pd9, ppc-Pd7, bus-Pd7, ppc-Pg1, gen-Pg1, ppc-Pg2, gen-Pg2, ppc-Pg3, gen-Pg3, ppc-Pg4, gen-Pg4, ppc-Pg5, gen-Pg5, ppc-Cost2, gencost-Cost2, ppc-Cost1, gencost-Cost1, ppc-Cost0, gencost-Cost0', file=op, flush=True) fncs.initialize() # transactive load components csv_load = 0 scaled_unresp = 0 scaled_resp = 0 resp_c0 = 0 resp_c1 = 0 resp_c2 = 0 resp_max = 0 gld_load = 0 # this is the actual # ================================== # Laurentiu Marinovici - 2017-12-14 actual_load = 0 new_bid = False # saveInd = 0 # saveDataDict = {} # =================================== while ts <= tmax: if ts >= tnext_opf: # expecting to solve opf one dt before the market clearing period ends, so GridLAB-D has time to use it idx = int((ts + dt) / period) % nloads bus = ppc['bus'] print( '<<<<< ts = {}, ppc-Pd5 = {}, bus-Pd5 = {}, ppc-Pd7 = {}, bus-Pd7 = {}, ppc-Pd9 = {}, bus-Pd9 = {} >>>>>>>' .format(ts, ppc["bus"][4, 2], bus[4, 2], ppc["bus"][6, 2], bus[6, 2], ppc["bus"][8, 2], bus[8, 2])) gen = ppc['gen'] branch = ppc['branch'] gencost = ppc['gencost'] csv_load = loads[idx, 0] bus[4, 2] = loads[idx, 1] bus[8, 2] = loads[idx, 2] print( '<<<<< ts = {}, ppc-Pd5 = {}, bus-Pd5 = {}, ppc-Pd7 = {}, bus-Pd7 = {}, ppc-Pd9 = {}, bus-Pd9 = {} >>>>>>>' .format(ts, ppc["bus"][4, 2], bus[4, 2], ppc["bus"][6, 2], bus[6, 2], ppc["bus"][8, 2], bus[8, 2])) # process the generator and branch outages for row in ppc['UnitsOut']: if ts >= row[1] and ts <= row[2]: gen[row[0], 7] = 0 else: gen[row[0], 7] = 1 for row in ppc['BranchesOut']: if ts >= row[1] and ts <= row[2]: branch[row[0], 10] = 0 else: branch[row[0], 10] = 1 bus[6, 2] = csv_load # ================================= # Laurentiu Marinovici - 2017-12-14 # bus[6,2] = csv_load + actual_load # ================================= for row in ppc['FNCS']: scaled_unresp = float(row[2]) * float(row[3]) newidx = int(row[0]) - 1 bus[newidx, 2] += scaled_unresp print( '<<<<< ts = {}, ppc-Pd5 = {}, bus-Pd5 = {}, ppc-Pd7 = {}, bus-Pd7 = {}, ppc-Pd9 = {}, bus-Pd9 = {} >>>>>>>' .format(ts, ppc["bus"][4, 2], bus[4, 2], ppc["bus"][6, 2], bus[6, 2], ppc["bus"][8, 2], bus[8, 2])) gen[4][9] = -resp_max * float(fncsBus[0][2]) gencost[4][3] = 3 gencost[4][4] = resp_c2 gencost[4][5] = resp_c1 gencost[4][6] = resp_c0 # ================================= # Laurentiu Marinovici - 2017-12-14 # print('Before running OPF:') # print('Disp load/neg gen: Pg = ', gen[4][1], ', Pmax = ', gen[4][8], ', Pmin = ', gen[4][9], ', status = ', gen[4][7]) # print('Disp load/neg gen cost coefficients: ', gencost[4][4], ', ', gencost[4][5], ', ', gencost[4][6]) # gen[4, 7] = 1 # turn on dispatchable load #ppc['gen'] = gen #ppc['bus'] = bus #ppc['branch'] = branch #ppc['gencost'] = gencost # print (ts, ppc["bus"][4, 2], ppc["bus"][8, 2], ppc["bus"][6, 2], bus[6, 2], ppc["gen"][0, 1], gen[0, 1], ppc["gen"][1, 1], gen[1, 1], ppc["gen"][2, 1], gen[2, 1], ppc["gen"][3, 1], gen[3, 1], ppc["gen"][4, 1], gen[4, 1], ppc["gencost"][4, 4], gencost[4, 4], ppc["gencost"][4, 5], gencost[4, 5], ppc["gencost"][4, 6], gencost[4, 6], sep=',', file=op, flush=True) # ===================================================================================================================== res = pp.runopf(ppc, ppopt) # ================================= # Laurentiu Marinovici - 2017-12-21 # mpcKey = 'mpc' + str(saveInd) # resKey = 'res' + str(saveInd) # saveDataDict[mpcKey] = copy.deepcopy(ppc) # saveDataDict[resKey] = copy.deepcopy(res) # saveInd += 1 # ================================= bus = res['bus'] gen = res['gen'] Pload = bus[:, 2].sum() Pgen = gen[:, 1].sum() Ploss = Pgen - Pload scaled_resp = -1.0 * gen[4, 1] # CSV file output print(ts, res['success'], '{:.3f}'.format(bus[:, 2].sum()), '{:.3f}'.format(csv_load), '{:.3f}'.format(scaled_unresp), '{:.3f}'.format(bus[6, 2]), '{:.3f}'.format(scaled_resp), '{:.3f}'.format(actual_load), new_bid, '{:.3f}'.format(gen[4, 9]), '{:.3f}'.format(bus[6, 7]), '{:.3f}'.format(bus[6, 13]), '{:.3f}'.format(bus[6, 14]), '{:.2f}'.format(gen[0, 1]), '{:.2f}'.format(gen[1, 1]), '{:.2f}'.format(gen[2, 1]), '{:.2f}'.format(gen[3, 1]), '{:.2f}'.format(res['gen'][4, 1]), '{:.6f}'.format(ppc['gencost'][4, 4]), '{:.4f}'.format(ppc['gencost'][4, 5]), '{:.4f}'.format(ppc['gencost'][4, 6]), sep=',', file=op, flush=True) fncs.publish('LMP_B7', 0.001 * bus[6, 13]) fncs.publish('three_phase_voltage_B7', 1000.0 * bus[6, 7] * bus[6, 9]) print('**OPF', ts, csv_load, scaled_unresp, gen[4][9], scaled_resp, bus[6, 2], 'LMP', 0.001 * bus[6, 13]) # update the metrics sys_metrics[str(ts)] = {rootname: [Ploss, res['success']]} bus_metrics[str(ts)] = {} for i in range(fncsBus.shape[0]): busnum = int(fncsBus[i, 0]) busidx = busnum - 1 row = bus[busidx].tolist() bus_metrics[str(ts)][str(busnum)] = [ row[13] * 0.001, row[14] * 0.001, row[2], row[3], row[8], row[7], row[11], row[12] ] gen_metrics[str(ts)] = {} for i in range(gen.shape[0]): row = gen[i].tolist() busidx = int(row[0] - 1) gen_metrics[str(ts)][str(i + 1)] = [ row[1], row[2], float(bus[busidx, 13]) * 0.001 ] tnext_opf += period if tnext_opf > tmax: print('breaking out at', tnext_opf, flush=True) break # apart from the OPF, keep loads updated ts = fncs.time_request(ts + dt) events = fncs.get_events() new_bid = False for key in events: topic = key.decode() # ================================== # Laurentiu Marinovici - 2017-12-14l # print('The event is: ........ ', key) # print('The topic is: ........ ', topic) # print('The value is: ........ ', fncs.get_value(key).decode()) # ============================================================= if topic == 'UNRESPONSIVE_KW': unresp_load = 0.001 * float(fncs.get_value(key).decode()) fncsBus[0][ 3] = unresp_load # poke unresponsive estimate into the bus load slot new_bid = True elif topic == 'RESPONSIVE_MAX_KW': resp_max = 0.001 * float(fncs.get_value(key).decode()) # in MW new_bid = True elif topic == 'RESPONSIVE_M': # resp_c2 = 1000.0 * 0.5 * float(fncs.get_value(key).decode()) resp_c2 = -1e6 * float(fncs.get_value(key).decode()) new_bid = True elif topic == 'RESPONSIVE_B': # resp_c1 = 1000.0 * float(fncs.get_value(key).decode()) resp_c1 = 1e3 * float(fncs.get_value(key).decode()) new_bid = True # ============================================ # Laurentiu Marinovici elif topic == 'RESPONSIVE_BB': resp_c0 = -float(fncs.get_value(key).decode()) new_bid = True # ============================================ elif topic == 'UNRESPONSIVE_PRICE': # not actually used unresp_price = float(fncs.get_value(key).decode()) new_bid = True else: gld_load = parse_mva(fncs.get_value(key).decode( )) # actual value, may not match unresp + resp load # ================================== # Laurentiu Marinovici - 2017-12-14 # print('GLD real = ', float(gld_load[0]), '; GLD imag = ', float(gld_load[1])) # print('Amp factor = ', float(fncsBus[0][2])) # ================================================================== actual_load = float(gld_load[0]) * float(fncsBus[0][2]) print(' Time = ', ts, '; actual load real = ', actual_load) if new_bid == True: print('**Bid', ts, unresp_load, resp_max, resp_c2, resp_c1, resp_c0) # Laurentiu Marinovici - 2017-12-21 # spio.savemat('matFile.mat', saveDataDict) # =================================== print('writing metrics', flush=True) print(json.dumps(bus_metrics), file=bus_mp, flush=True) print(json.dumps(gen_metrics), file=gen_mp, flush=True) print(json.dumps(sys_metrics), file=sys_mp, flush=True) print('closing files', flush=True) bus_mp.close() gen_mp.close() sys_mp.close() op.close() print('finalizing FNCS', flush=True) fncs.finalize()