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 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 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 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 reset(self): # find Vtheta net for b in self.ppc['bus']: if (b[1] == 3): self.vbus = int(b[0]) break # for vbus generator, add 2 actions (up/down)(V) if (self.vbus in self.ppc['gen'][:, 0]): self.action_space.append(-1) self.action_space.append(-2) # for each generator, add 4 actions (up/down)(P/V)(P/Q) for index, g in enumerate(self.ppc['gen']): self.genmap[int(g[0])] = index i = int(g[0]) # skip Vtheta net if (i == self.vbus): continue # set uncontrollable generator elif i in DICT1.keys(): g[1] = DICT1[i] else: self.action_space.append(4 * i) self.action_space.append(4 * i + 1) self.action_space.append(4 * i + 2) self.action_space.append(4 * i + 3) # build actmap for i, act in enumerate(self.action_space): self.actmap[i] = act # initialize powerflow self.results, self.success = runpf(self.ppc, self.ppopt) self.observation = self.getobservation() self.state = self.getstate() return self.observation
def pf(args=sys.argv[1:]): usage = 'Runs a power flow.' options, casedata, ppopt, fname, solvedcase = \ parse_options(args, usage) if options.test: sys.exit(test_pf()) _, success = runpf(casedata, ppopt, fname, solvedcase) exit(success)
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 get_output(self,*args): #returns the output of the load flow calculation for k in range(1,29): self.ppc["gen"][k,1] = self.dispatch_load[k] ppc_result, y = runpf(self.ppc, self.ppopt) if args: self.add_noise(args[0]) #print ppc_result["bus"][1,12] #print ppc_result["bus"][6,7] #print ppc_result["bus"][12,7] #print ppc_result["bus"][18,7] #print ppc_result["bus"][24,7] branch_constraints = array([(ppc_result["bus"][7,7] < (ppc_result["bus"][1,12])) , ppc_result["bus"][14,7] < (ppc_result["bus"][1,12]) , ppc_result["bus"][21,7] < (ppc_result["bus"][1,12]), ppc_result["bus"][28,7] < (ppc_result["bus"][1,12])]) #print self.ppc["gen"][:,1] if any(branch_constraints == True): while(any(branch_constraints == True)): for k in range(0,4): if branch_constraints[k] == True: self.adapt_branch_power(ppc_result,k) self.adapt_main_generator() ppc_result, y = runpf(self.ppc, self.ppopt) #print self.ppc["gen"][:,1] for k in range(0,4): if branch_constraints[k] == True: branch_constraints[k] = (abs(ppc_result["bus"][k * 7+ 7,7] - ppc_result["bus"][1,12]) > 0.001) #print ppc_result["bus"][6,7] #print ppc_result["bus"][12,7] #print ppc_result["bus"][18,7] #print ppc_result["bus"][24,7] #print branch_constraints return ppc_result
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 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 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 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 updateGraphFlow(self,graph,case): solverResult = None try: solverResult = runpf(case, ppopt=ppoption()) # get from the results branches with counters if there is more branches between two buses counters = [] i = 0 for branch in solverResult[0]["branch"]: fromBusTemp = int(branch[constOut["branch"]["fromBus"]]) toBusTemp = int(branch[constOut["branch"]["toBus"]]) pIn = branch[constOut["branch"]["Pin"]] first_or_default = next( (x for x in counters if x["fromBus"] == fromBusTemp and x["toBus"] == toBusTemp), None) if first_or_default is None: counters.append({"fromBus": fromBusTemp, "toBus": toBusTemp, "counter": 0, "Pin": pIn, "index": i}) else: counters.append( {"fromBus": fromBusTemp, "toBus": toBusTemp, "counter": first_or_default["counter"] + 1, "Pin": pIn, "index": i}) i = i + 1 # for all vertices assign 0.0 for Pin and 0.0 for Pg for v in graph.vs: v["Pin"] = 0.0 v["Pout"] = 0.0 v["Pg"] = 0.0 for gen in solverResult[0]["gen"]: busName = "Bus_" + str(int(gen[0])) graph.vs.find(busName)["Pg"] = gen[1] for c in counters: f = graph.vs.find("Bus_" + str(c["fromBus"])) t = graph.vs.find("Bus_" + str(c["toBus"])) graph.es.select(_source=f.index, _target=t.index)[c["counter"]]["Pin"] = c["Pin"] if (c["Pin"] > 0): t["Pin"] += c["Pin"] f["Pout"] += c["Pin"] else: f["Pin"] += math.fabs(c["Pin"]) t["Pout"] += math.fabs(c["Pin"]) except ValueError as ve: logging.error(ve) raise SimException(ve.message)
from pypower.api import case9,runpf from runPfOptions import ppoption import const succes=runpf(case9(),ppopt=ppoption()); # print(succes[0]['branch']) print(succes[0]['bus']) for branch in succes[0]['branch']: print branch[const.constOut['branch']["Pin"]] print branch[const.constOut['branch']["Pout"]] print("done")
C = 1 * Cbest pOption.remove(bestIdx) pIdx.append(bestIdx) pilotBus = [lIdx[i] for i in pIdx] return pilotBus if __name__ == '__main__': print('-----------Start-----------') ppc, success = runpf(case9()) ppc = ext2int(ppc) baseMVA = ppc['baseMVA'] bus = ppc['bus'] branch = ppc['branch'] Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch) vm = bus[:, VM] va = 2 * np.pi * bus[:, VA] V = vm * np.exp(1j * va) gIdx = [0, 1, 2] lIdx = [3, 4, 5, 6, 7, 8] nPilot = 2
for n in range(len(time)): casedata['bus'][ bus_var, 2] = loadsP15to25[:, n] #Changing the values for the active power casedata['bus'][ bus_var, 3] = loadsQ15to25[:, n] #Changing the values for the reactive power #casedata['bus'][3,2] = LoadP[n] #Changing the values for PV values (active power), reactive==0 ??? casedata['gen'][1, 1] = LoadP[n] / ( baseMVA * 1000 ) #genP19[:,n] #Changing the values for the gen-active power casedata['gen'][ 1, 2] = 0 #genQ19[:,n] #Changing the values for the gen-reactive power ppopt = ppoption(PF_ALG=2) resultPF, success = runpf(casedata, ppopt) print if success == 0: print('ERROR in step %d', n) slack_ang = resultPF['bus'][1, 8] v_mag[:, n] = resultPF['bus'][:, 7] # Voltage, magnitude v_ang[:, n] = resultPF['bus'][:, 8] - slack_ang # Voltage, angle loadP_all[:, n] = resultPF['bus'][:, 2] loadQ_all[:, n] = resultPF['bus'][:, 3] genP_all[:, n] = resultPF['gen'][:, 1] genQ_all[:, n] = resultPF['gen'][:, 2] P_into_00[:, n] = -resultPF['branch'][0, 15] Q_into_00[:, n] = -resultPF['branch'][0, 16]
def simulate_data(Sm, gen=None, PVdata=None, PV_idx=None, verbose = 0): """ Simulate data using power flow analysis :param PVgen: data from PV generation injected at bus 6 :return: dict """ from scipy.io import loadmat S=Sm.copy() t_ges = 1440 delta_t = 15 time= np.arange(delta_t, t_ges+delta_t,delta_t) t_f = len(time) bus_var = np.arange(2,13,1) # buses that are varied v_mag = np.zeros((13,t_f)) v_ang = np.zeros((13,t_f)) P = np.zeros((13,t_f)) Q = np.zeros((13,t_f)) loadP = np.zeros((13,t_f)) loadQ = np.zeros((13,t_f)) genP_all = np.zeros((2,t_f)) genQ_all = np.zeros((2,t_f)) P_into_00 = np.zeros(t_f) Q_into_00 = np.zeros(t_f) if (len(bus_var)==S.shape[0]): Pdata = np.real(S) Qdata = np.imag(S) elif (2*len(bus_var)==S.shape[0]): Pdata = S[:S.shape[0]/2,:] Qdata = S[S.shape[0]/2:,:] else: raise ValueError("Powers have wrong dimension.") if isinstance(PVdata,np.ndarray): if len(PVdata.shape)==2: # P and Q for PVgen if not PVdata.shape[0]==2: PVdata = PVdata.T Pdata[PV_idx,:] = -PVdata[0,:]+Pdata[PV_idx,:] Qdata[PV_idx,:] = -PVdata[1,:]+Qdata[PV_idx,:] else: Pdata[PV_idx,:] = -PVdata[:] +Pdata[PV_idx,:]# with MVA Qdata[PV_idx,:] = np.zeros_like(PVdata) casedata = get_topology() for n in range(len(time)): casedata['bus'][bus_var,2] = Pdata[:,n] #Changing the values for the active power casedata['bus'][bus_var,3] = Qdata[:,n] #Changing the values for the reactive power if isinstance(gen,np.ndarray): casedata['gen'][1,1] = gen[n] casedata['gen'][1,2] = 0 ppopt = ppoption(PF_ALG=2) ppopt["VERBOSE"] = verbose resultPF, success = runpf(casedata, ppopt) if success == 0: print ('ERROR in step %d', n) slack_ang = resultPF['bus'][1,8] v_mag[:,n] = resultPF['bus'][:,7] # Voltage, magnitude v_ang[:,n] = resultPF['bus'][:,8] - slack_ang # Voltage, angle loadP[:,n] = resultPF['bus'][:,2] loadQ[:,n] = resultPF['bus'][:,3] genP_all[:,n] = resultPF['gen'][:,1] genQ_all[:,n] = resultPF['gen'][:,2] P_into_00[n]=-resultPF['branch'][0,15] Q_into_00[n]=-resultPF['branch'][0,16] loadP[6,:] = loadP[6,:]+genP_all[1,:] loadQ[6,:] = loadQ[6,:]+genQ_all[1,:] simdata = dict([]) simdata["Vm"] = (11/(np.sqrt(3)))*v_mag simdata["Va"] = v_ang simdata["Pk"] = -loadP[2:,:] simdata["Qk"] = -loadQ[2:,:] simdata["P_00"]=P_into_00 simdata["Q_00"]=Q_into_00 return simdata
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: for ld in sample:
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 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 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'] gen = ppc['gen'] ppopt_market = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=1) ppopt_regular = 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 # 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 key in events: topic = key.decode() if topic == 'UNRESPONSIVE_MW': unresp = load_scale * float(fncs.get_value(key).decode()) 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(fncs.get_value(key).decode()) new_bid = True elif topic == 'RESPONSIVE_C2': resp_c2 = float(fncs.get_value(key).decode()) / load_scale new_bid = True elif topic == 'RESPONSIVE_C1': resp_c1 = float(fncs.get_value(key).decode()) new_bid = True elif topic == 'RESPONSIVE_DEG': resp_deg = int(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 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] += unresp # 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 # TODO, if more than one FNCS bus, track scaled_resp separately 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] 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 ts = fncs.time_request(ts + dt) if ts > tmax: print('breaking out at', ts, flush=True) break # spio.savemat('matFile.mat', saveDataDict) # =================================== 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()
from pypower.api import case9, ppoption, runpf, printpf from constants import * import numpy as np # See http://rwl.github.io/PYPOWER/api/ for description of variables ''' Slack Bus: At the slack bus, the voltage magnitude and angle are fixed and the power injections are free. There is only one slack bus in a power system. Load Bus: At a load bus, or PQ bus, the power injections are fixed while the voltage magnitude and angle are free. There are M PQ buses in the system. Voltage-Controlled Bus: At a voltage controlled bus, or PV bus, the real power injection and voltage magnitude are fixed while the reactive power injection and the voltage angle are free. (This corresponds to allowing a local source of reactive power to regulate the voltage to a desired setpoint.) There are N − M − 1 PV buses in the system. ''' ppc = case9() ppopt = ppoption(PF_ALG=2, VERBOSE=0, OUT_ALL=0) r1, succeed = runpf(ppc, ppopt) print("Success:", succeed) ppc['gen'][2, PG] = 100000.0 r2, succeed = runpf(ppc, ppopt) print("Success:", succeed)
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)
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 temp = bus_out.bus_out(temp, c) #modify data according to outage (r, s) = runpf(temp, ppopt) #run load flow if s == 1: check_sol.check_sol(n_out, r) #check violations for convg case else: #print results if divergent case print_sim_results.print_sim_results(s, n_out, r, 0, 0, 0, 0) success.append(s) del s, r, temp c += 1 n_out += 1 # Simulate gen outages c = 0 # start counter while c < ngen_out: temp = casea.casef() temp = gen_out.gen_out(temp, c)
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) #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.")
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() V_DDLF = run_ddlf(ppc, epsilon=1.e-5) time_DDLF = timeit.default_timer() - start_time print("\n\t Direct PF converged in {0} s".format(time_DDLF))
@author: saur ''' from cases_second import cases from pypower.api import ppoption, runopf, runpf from numpy import linspace from scipy import array,ones , zeros import matplotlib.pyplot as plt from scipy.stats import linregress time = 72 test_object = cases(time) #test_object.set_base(time) result , y = runpf(test_object.ppc,test_object.ppopt) power = linspace(0,25,num=25) slopes = zeros(6) power_data_matrix = zeros((25,6)) voltage_data_matrix = zeros((25,6)) for index in range(2,8): count = 0 voltages = zeros(25) powers = zeros(25) for p in power: test_object = cases(time) test_object.ppc["gen"][index-1,1] = - p /1000.0 result , y = runpf(test_object.ppc,test_object.ppopt) #print result power_data_matrix[count, index - 2] = p
ppc['bus'][:, 13] = opf_bus[:, 13] # set the lmp ppc['gen'][:, 1] = opf_gen[:, 1] # set the economic dispatch # add the actual scaled GridLAB-D loads to the baseline curve loads, turn off dispatchable loads for row in fncs_bus: busnum = int(row[0]) gld_scale = float(row[2]) Pgld = gld_load[busnum]['p'] * gld_scale Qgld = gld_load[busnum]['q'] * gld_scale ppc['bus'][busnum - 1, 2] = gld_load[busnum]['pcrv'] + Pgld ppc['bus'][busnum - 1, 3] = gld_load[busnum]['qcrv'] + Qgld genidx = gld_load[busnum]['genidx'] ppc['gen'][genidx, 1] = 0 # p ppc['gen'][genidx, 2] = 0 # q ppc['gen'][genidx, 9] = 0 # pmin # print_gld_load (ppc, gld_load, 'RPF', ts) rpf = pp.runpf(ppc, ppopt_regular) if rpf[0]['success'] == False: conv_accum = False print('rpf did not converge at', ts) # pp.printpf (100.0, # bus=rpf[0]['bus'], # gen=rpf[0]['gen'], # branch=rpf[0]['branch'], # fd=sys.stdout, # et=rpf[0]['et'], # success=rpf[0]['success']) bus = rpf[0]['bus'] gen = rpf[0]['gen'] fncsBus = ppc['FNCS'] Pload = bus[:, 2].sum() Pgen = gen[:, 1].sum()
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( (LMP_solved, results_opf['bus'][:, 13])) opf_time = time_opf[0:k + 1] / 3600 k = k + 1 ################################ Running PF For optimal power flow intervals ############################## solved_pf = runpf(ppc, ppopt) results_pf = solved_pf[0] ppc['bus'] = results_pf['bus'] ppc['gen'] = results_pf['gen'] if (results_pf['success'] == 1): if (x == 0): voltages = results_pf['bus'][:, 7] real_demand = results_pf['bus'][:, 2] distribution_load = [rload / 1000000] else: voltages = numpy.vstack((voltages, results_pf['bus'][:, 7])) real_demand = numpy.vstack((real_demand, results_pf['bus'][:, 2])) distribution_load.append(rload / 1000000) pf_time = time_pf[0:x + 1] / 3600
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 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)))
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()
''' Created on Mar 16, 2015 @author: saur ''' from cases_alternative_model import cases from agent import agent from pypower.api import ppoption, runopf, runpf min_value_voltage = 0.99 for time in range(0, 96): testcase = cases(time) testcase.set_base(time) result, y = runpf(testcase.ppc, testcase.ppopt) print min(result["bus"][:, 7]) if min(result["bus"][:, 7]) < min_value_voltage: min_value_voltage = min(result["bus"][:, 7]) print min_value_voltage """ #create the agents SOC_initial = 5 agents = dict() for k in range(2,26): agents[k]= agent(SOC_initial,k,time_init) ##here is what has to be repeated over and over again. ## each agent does something to the environment testcase.set_base(time_init) #for i in agents: # agents[i].do_interaction(testcase)
from pypower.api import case14, ppoption, runpf, printpf ppc = case14() ppopt = ppoption(PF_ALG=2) r = runpf(ppc,ppopt) printpf(r)
def step(self, action): action = self.actmap[action] # transfer act if (action > 0): num = self.genmap[int(action / 4)] # gen number move = int(action % 4) # type of move reward = 0 # Default reward and done state done = False if action == -1: self.ppc['gen'][self.genmap[self.vbus]][5] += VUNIT elif action == -2: self.ppc['gen'][self.genmap[self.vbus]][5] -= VUNIT elif move == 0: # P up by UNIT self.ppc['gen'][num][1] += PUNIT elif move == 1: # P down by UNIT self.ppc['gen'][num][1] -= PUNIT elif move == 2 and self.ppc['bus'][int(action / 4)][1] == 2: self.ppc['gen'][num][5] += VUNIT elif move == 2 and self.ppc['bus'][int(action / 4)][1] == 1: self.ppc['gen'][1][2] += QUNIT elif move == 3 and self.ppc['bus'][int(action / 4)][1] == 2: self.ppc['gen'][num][5] -= VUNIT elif move == 3 and self.ppc['bus'][int(action / 4)][1] == 1: self.ppc['gen'][1][2] -= QUNIT # limit PQ of generator for g in self.ppc['gen']: if g[1] > g[8] > 0: g[1] = g[8] elif g[1] < g[9]: g[1] = g[9] elif g[2] > g[3]: g[2] = g[3] elif g[2] < g[4]: g[2] = g[4] # randomnize the output of uncontrolled generator # for g in self.ppc['gen']: # i=int(g[0]) # if i in DICT1.keys(): # g[1] += 10*np.random.rand()-5 #Use pypower to calculate pf self.results, self.success = runpf(self.ppc, self.ppopt) #get the next state s_ = self.getstate() #get observation self.observation = self.getobservation() # reward function # if voltage is out of range, reward = -1 if s_['Vmin'] <= LOW or s_['Vmax'] >= HIGH: reward = 0 done = True # if loss is lower than before, reward = 1 elif s_['loss'] < self.state['loss']: reward = 1 done = False self.state = s_ return self.observation, reward, done
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 get_voltage(self, node): #returns the voltage at specific node after running power flow simulation ppc_result, y = runpf(self.ppc, self.ppopt) #print ppc_result["bus"][node,7] return ppc_result["bus"][node, 7]
def simulate_data(Sm, gen=None, PVdata=None, PV_idx=None, verbose=0): """ Simulate data using power flow analysis :param PVgen: data from PV generation injected at bus 6 :return: dict """ from scipy.io import loadmat S = Sm.copy() t_ges = 1440 delta_t = 15 time = np.arange(delta_t, t_ges + delta_t, delta_t) t_f = len(time) bus_var = np.arange(2, 13, 1) # buses that are varied v_mag = np.zeros((13, t_f)) v_ang = np.zeros((13, t_f)) P = np.zeros((13, t_f)) Q = np.zeros((13, t_f)) loadP = np.zeros((13, t_f)) loadQ = np.zeros((13, t_f)) genP_all = np.zeros((2, t_f)) genQ_all = np.zeros((2, t_f)) P_into_00 = np.zeros(t_f) Q_into_00 = np.zeros(t_f) if (len(bus_var) == S.shape[0]): Pdata = np.real(S) Qdata = np.imag(S) elif (2 * len(bus_var) == S.shape[0]): Pdata = S[:S.shape[0] / 2, :] Qdata = S[S.shape[0] / 2:, :] else: raise ValueError("Powers have wrong dimension.") if isinstance(PVdata, np.ndarray): if len(PVdata.shape) == 2: # P and Q for PVgen if not PVdata.shape[0] == 2: PVdata = PVdata.T Pdata[PV_idx, :] = -PVdata[0, :] + Pdata[PV_idx, :] Qdata[PV_idx, :] = -PVdata[1, :] + Qdata[PV_idx, :] else: Pdata[PV_idx, :] = -PVdata[:] + Pdata[PV_idx, :] # with MVA Qdata[PV_idx, :] = np.zeros_like(PVdata) casedata = get_topology() for n in range(len(time)): casedata['bus'][ bus_var, 2] = Pdata[:, n] #Changing the values for the active power casedata['bus'][ bus_var, 3] = Qdata[:, n] #Changing the values for the reactive power if isinstance(gen, np.ndarray): casedata['gen'][1, 1] = gen[n] casedata['gen'][1, 2] = 0 ppopt = ppoption(PF_ALG=2) ppopt["VERBOSE"] = verbose resultPF, success = runpf(casedata, ppopt) if success == 0: print('ERROR in step %d', n) slack_ang = resultPF['bus'][1, 8] v_mag[:, n] = resultPF['bus'][:, 7] # Voltage, magnitude v_ang[:, n] = resultPF['bus'][:, 8] - slack_ang # Voltage, angle loadP[:, n] = resultPF['bus'][:, 2] loadQ[:, n] = resultPF['bus'][:, 3] genP_all[:, n] = resultPF['gen'][:, 1] genQ_all[:, n] = resultPF['gen'][:, 2] P_into_00[n] = -resultPF['branch'][0, 15] Q_into_00[n] = -resultPF['branch'][0, 16] loadP[6, :] = loadP[6, :] + genP_all[1, :] loadQ[6, :] = loadQ[6, :] + genQ_all[1, :] simdata = dict([]) simdata["Vm"] = (11 / (np.sqrt(3))) * v_mag simdata["Va"] = v_ang simdata["Pk"] = -loadP[2:, :] simdata["Qk"] = -loadQ[2:, :] simdata["P_00"] = P_into_00 simdata["Q_00"] = Q_into_00 return simdata
def mainJAPowerFlow(baseMVAName, busName, genName, branchName, splitCharacter, outputBusName, outputBranchName, outputGenName, printOutput, optimal, areasName, genCostName, convergedOutputName): #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" #convergedOutputName = "outputStatus.txt", which will have three lines. The first will just be the inputs variables given (inputs to mainJAPowerFLow). The second of which will state "0" (if it did not converge) or "1" (if it converged), while the third line will state this in text as "Converged!" (if it converged) or "Diverged!" (if it did not). Note that the "'s are not printed, just to show the contents. Also note that the second and third lines show the same information in different formats. #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 (so prints to terminal if 1 and does not if 0) #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.") #Output Metadata, which outputs the input variables to the function as well as if the model converged as described in the convergedOutputName description above. out = open(convergedOutputName, 'w') out.write(baseMVAName + splitCharacter + busName + splitCharacter + genName + splitCharacter + branchName + splitCharacter + splitCharacter + splitCharacter + outputBusName + splitCharacter + outputBranchName + splitCharacter + outputGenName + splitCharacter + str(printOutput) + splitCharacter + str(optimal) + splitCharacter + areasName + splitCharacter + genCostName + splitCharacter + convergedOutputName + '\n') if (optimal == 1): #If this is OPF the convergence can be found as follows. if (r['success'] == True): print("Converged.") out.write("1\n") out.write("Converged!\n") else: print("Did not converge.") out.write("0\n") out.write("Diverged!\n") elif (optimal == 0): #For some reason this doesn't work for just PF, so will check in a more crude mannor. if ("'success': 1" in str(r)): print("Converged.") out.write("1\n") out.write("Converged!\n") else: print("Did not converge.") out.write("0\n") out.write("Diverged!\n") out.close() #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): 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() #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.")