def faultPlot(bus_coord): ''' Plot fault study. ''' dss.run_command('Solve Mode=FaultStudy') dss.run_command('Export fault faults.csv') faultData = pd.read_csv('faults.csv') bus_coord.columns = ['Bus', 'X', 'Y', 'radius'] # Add defined column names. faultDF = pd.concat([bus_coord, faultData], axis=1) faultDF.columns = faultDF.columns.str.strip() plt.scatter(faultDF['radius'], faultDF['3-Phase']) plt.xlabel('Distance [m]') plt.ylabel('Current [Amps]') plt.axis([-1, 6, 0, 8000]) plt.savefig('3-Phase.png') plt.clf() plt.scatter(faultDF['radius'], faultDF['1-Phase']) plt.xlabel('Distance [m]') plt.ylabel('Current [Amps]') plt.savefig('1-phase.png') plt.axis([-1, 6, 0, 8000]) plt.clf() plt.scatter(faultDF['radius'], faultDF['L-L']) plt.xlabel('Distance [m]') plt.ylabel('Current [Amps]') plt.axis([-1, 6, 0, 8000]) plt.savefig('L-L.png') plt.clf() packagePlots('FaultPlots')
def create_dict(output_dir): """Do the fault study for each reader and create a dictonary which contains the sequence impedances for each node. These values are used for comparison of fault study of readers""" comp_values = defaultdict() for case_dir in os.listdir(output_dir): comp_values[case_dir] = defaultdict() for dir_name in os.listdir(os.path.join(output_dir, case_dir)): comp_values[case_dir][dir_name] = {} with open( os.path.join(output_dir, case_dir, dir_name, "Master.dss"), "r") as rfile: filedata = rfile.read() filedata = filedata.replace("Solve", "Solve mode=faultstudy") with open( os.path.join(output_dir, case_dir, dir_name, "Faultstudy_Master.dss"), "w", ) as file: file.write(filedata) dss.run_command("Redirect {}".format( os.path.join(output_dir, case_dir, dir_name, "Faultstudy_Master.dss"))) for i in dss.Circuit.AllBusNames(): dss.Circuit.SetActiveBus(i) comp_values[case_dir][dir_name][dss.Bus.Name()] = ( dss.Bus.Zsc0() + dss.Bus.Zsc1()) return comp_values
def _clean_data(data, class_name): import opendssdirect as dss for element in dss.ActiveClass.AllNames(): name = "{class_name}.{element}".format(class_name=class_name, element=element) dss.ActiveClass.Name(element) if "nconds" in dss.Element.AllPropertyNames(): nconds = int(data[name]["nconds"]) x = [] h = [] units = [] for cond in range(1, nconds + 1): dss.run_command("{name}.cond={cond}".format(name=name, cond=cond)) x.append(float(dss.run_command( "? {name}.x".format(name=name)))) h.append(float(dss.run_command( "? {name}.h".format(name=name)))) units.append( dss.run_command("? {name}.units".format(name=name))) data[name]["x"] = x data[name]["h"] = h data[name]["units"] = units return data
def compile_feeder_initialize(self): self.break_flag = 0 dss.run_command("Clear") dss.Basic.ClearAll() Master_file = os.path.join(self.Settings["Feeder_path"], self.folders, self.sub_folder, self.feeder, "Master.dss") print(Master_file) if not os.path.exists(Master_file): print("error {} does not exist".format(Master_file)) self.break_flag = 1 if self.break_flag == 0: try: # Solve base no DPV case: If base no DPV is outside ANSI B limits abort command_string = "Redirect {master}".format(master=Master_file) # self.write_dss_file(command_string) k = dss.run_command(command_string) if len(k) > 1: self.break_flag = 1 command_string = "Solve mode=snap" # self.write_dss_file(command_string) dss.run_command(command_string) self.sol.Solve() except: self.break_flag == 1 print("here")
def voltagePlot(filePath, PU=True): ''' Voltage plotting routine.''' dssFileLoc = os.path.dirname(os.path.abspath(filePath)) volt_coord = runDSS(filePath) dss.run_command('Export voltages ' + dssFileLoc + '/volts.csv') # Generate voltage plots. voltage = pd.read_csv(dssFileLoc + '/volts.csv') volt_coord.columns = ['Bus', 'X', 'Y', 'radius'] voltageDF = pd.merge( volt_coord, voltage, on='Bus') # Merge on the bus axis so that all data is in one frame. plt.title('Voltage Profile') plt.xlabel('Distance from source[miles]') if PU: for i in range(1, 4): volt_ind = ' pu' + str(i) plt.scatter(voltageDF['radius'], voltageDF[volt_ind], label='Phase ' + str(i)) plt.ylabel('Voltage [PU]') plt.legend() plt.savefig(dssFileLoc + '/Voltage Profile [PU].png') else: # plt.axis([1, 7, 2000, 3000]) # Ignore sourcebus-much greater-for overall magnitude. for i in range(1, 4): mag_ind = ' Magnitude' + str(i) plt.scatter(voltageDF['radius'], voltageDF[mag_ind], label='Phase ' + str(i)) plt.ylabel('Voltage [V]') plt.legend() plt.savefig(dssFileLoc + '/Voltage Profile [V].png') plt.clf()
def voltagePlots(volt_coord): ''' Voltage plotting routine.''' dss.run_command('Export voltages volts.csv') # Generate voltage plots. voltage = pd.read_csv('volts.csv') volt_coord.columns = ['Bus', 'X', 'Y', 'radius'] voltageDF = pd.merge( volt_coord, voltage, on='Bus') # Merge on the bus axis so that all data is in one frame. for i in range(1, 4): volt_ind = ' pu' + str(i) mag_ind = ' Magnitude' + str(i) plt.scatter(voltageDF['radius'], voltageDF[volt_ind]) plt.xlabel('Distance from source[miles]') plt.ylabel('Voltage [PU]') plt.title('Voltage profile for phase ' + str(i)) plt.savefig('Pu Profile ' + str(i) + '.png') # A per unit plot. plt.clf() plt.scatter(voltageDF['radius'], voltageDF[mag_ind]) plt.xlabel('Distance from source[miles]') plt.ylabel('Volt [V]') plt.axis([1, 7, 2000, 3000 ]) # Ignore sourcebus-much greater-for overall magnitude. plt.title('Voltage profile for phase ' + str(i)) plt.savefig('Magnitude Profile ' + str(i) + '.png') # Actual voltages. plt.clf() packagePlots('voltagePlots')
def test_cyme_to_opendss(): ''' Test the Cyme to OpenDSS conversion. ''' list_of_directories = [] from ditto.store import Store from ditto.readers.cyme.read import Reader from ditto.writers.opendss.write import Writer import opendssdirect as dss cyme_models = [ f for f in os.listdir( os.path.join(current_directory, 'data/small_cases/cyme/')) if not f.startswith('.') ] for model in cyme_models: print(model) m = Store() r = Reader(data_folder_path=os.path.join( current_directory, 'data/small_cases/cyme', model)) r.parse(m) #TODO: Log properly # print('>Cyme model {model} read...'.format(model=model)) output_path = tempfile.TemporaryDirectory() list_of_directories.append(output_path) w = Writer(output_path=output_path.name) w.write(m) #TODO: Log properly # print('>...and written to OpenDSS.\n') print(model) dss.run_command("clear")
def THD(filePath): ''' Calculate and plot total harmonic distortion. ''' dssFileLoc = os.path.dirname(os.path.abspath(filePath)) bus_coords = runDSS(filePath) dss.run_command('Solve mode=harmonics') dss.run_command('Export voltages ' + dssFileLoc + '/voltharmonics.csv') # Clean up temp file. try: base = os.path.basename(filePath) fnameMinusExt = os.path.splitext(base)[0] os.remove('{}_SavedVoltages.dbl'.format(fnameMinusExt)) except: pass voltHarmonics = pd.read_csv(dssFileLoc + '/voltharmonics.csv') bus_coords.columns = ['Bus', 'X', 'Y', 'radius'] voltHarmonics.columns.str.strip() for index, row in voltHarmonics.iterrows(): voltHarmonics['THD'] = row[' Magnitude1'] / ( math.sqrt(row[' Magnitude2']**2 + row[' Magnitude3']**2)) distortionDF = pd.merge( bus_coords, voltHarmonics, on='Bus') # Merge on the bus axis so that all data is in one frame. plt.scatter(distortionDF['radius'], distortionDF['THD']) plt.xlabel('Distance from Source [miles]') plt.ylabel('THD [Percentage]') plt.title('Total Harmonic Distortion') plt.savefig(dssFileLoc + '/THD.png') plt.clf()
def DSS_lines_3ph(iline, timestep): # Helper function for DSS_lines r11 = iline.R[0, 0] r12 = iline.R[1, 0] r22 = iline.R[1, 1] r13 = iline.R[2, 0] r23 = iline.R[2, 1] r33 = iline.R[2, 2] x11 = iline.X[0, 0] x12 = iline.X[1, 0] x22 = iline.X[1, 1] x13 = iline.X[2, 0] x23 = iline.X[2, 1] x33 = iline.X[2, 2] dss.run_command("New Line." + iline.name + " Bus1=" + iline.from_node.name + ".1.2.3 Bus2=" + iline.to_node.name + ".1.2.3 BaseFreq=60 Phases=3" + " rmatrix = (" + str(r11) + " | " + str(r12) + " " + str(r22) + " | " + str(r13) + " " + str(r23) + " " + str(r33) + ")" + " xmatrix = (" + str(x11) + " | " + str(x12) + " " + str(x22) + " | " + str(x13) + " " + str(x23) + " " + str(x33) + ")") return
def CreateBusObjects(): dssBuses = {} BusNames = dss.Circuit.AllBusNames() dss.run_command('New Fault.DEFAULT Bus1={} enabled=no r=0.01'.format( BusNames[0])) for BusName in BusNames: dss.Circuit.SetActiveBus(BusName) dssBuses[BusName] = dssBus() return dssBuses
def loadDSS(): current_directory = os.path.realpath(os.path.dirname(__file__)) master_file = os.path.join(current_directory, '../data/DSS_files/master.dss') dss.Basic.DataPath(current_directory) dss.run_command("clear") dss.run_command('compile {master}'.format(master=master_file)) return dss
def parse_DSS_file(self): print("Compiling DSS file in OpenDSS...") dss.run_command(r'{:}'.format(self.file)) print("Parsing DSS file in LogV3LPF format...") DSScase.get_capacitors_from_dss(self) DSScase.get_transformers_from_dss(self) DSScase.get_loads_from_dss(self) DSScase.get_lines_from_dss(self) DSScase.get_regcontrols_from_dss(self) DSScase.get_buses_from_dss(self) DSScase.get_constants(self) DSScase.create_load_model(self) print("Done parsing")
def networkPlot(coords): ''' Plot the physical topology of the circuit. ''' dss.run_command('Export voltages volts.csv') volts = pd.read_csv('volts.csv') coords.columns = ['Bus', 'X', 'Y', 'radius'] G = nx.Graph() # Declare networkx object. pos = {} for index, row in coords.iterrows(): # Get the coordinates. if row['Bus'] == '799R': row['Bus'] = '799r' if row['Bus'] == 'SOURCEBUS': row['Bus'] = 'SourceBus' G.add_node(row['Bus']) pos[row['Bus']] = (row['X'], row['Y']) volt_values = {} labels = {} for index, row in volts.iterrows( ): # We'll color the nodes according to voltage. FIX: pu1? if row['Bus'] == '799R': row['Bus'] = '799r' if row['Bus'] == 'SOURCEBUS': row['Bus'] = 'SourceBus' volt_values[row['Bus']] = row[' pu1'] labels[row['Bus']] = row['Bus'] colorCode = [volt_values[node] for node in G.nodes()] lines = dss.utils.lines_to_dataframe( ) # Get the connecting edges using Pandas. edges = [] for index, row in lines.iterrows( ): # For 799R, you need four charactesr. The others all have a period at the end, so splice that. bus1 = row['Bus1'][:4].replace('.', '') bus2 = row['Bus2'][:4].replace('.', '') edges.append((bus1, bus2)) G.add_edges_from(edges) nodes = nx.draw_networkx_nodes( G, pos, node_color=colorCode ) # We must seperate this to create a mappable object for colorbar. edges = nx.draw_networkx_edges(G, pos) nx.draw_networkx_labels(G, pos, labels) # We'll draw the labels seperately. plt.colorbar(nodes) plt.xlabel('Distance [m]') plt.title('Network Voltage Layout') plt.savefig('networkPlot.png') plt.clf() packagePlots('networkPlots')
def _constructYMatrix(self): ''' Calculate the nodal admittance matrix YMatrix Returns ------- numpy array It returns a complex array of Y admittance matrix ''' #- disconnect vsources and loads dss.run_command('vsource.source.enabled = no') dss.run_command('batchedit load..* enabled=no') #- extract YMatrix dss.Solution.Solve() Ybus = dss.Circuit.SystemY() #--- slow Yres = np.reshape(Ybus, (self._nNodes, self._nNodes * 2)) #--- slow #- populate complex polyphase nodal Y Y = np.zeros((self._nNodes, self._nNodes), dtype=complex) for i in range(self._nNodes): #--- very very slow Y[:, i] = Yres[:, 2 * i] + 1j * Yres[:, 2 * i + 1] self._YMatrixPrev = self._YMatrix self._YMatrix = Y #- reconnect vsources and loads dss.run_command('vsource.source.enabled = yes') dss.run_command('batchedit load..* enabled=yes') #- return to the previous solution dss.Solution.Solve() return Y
def _readInelasticLoadPQ(self, file): ''' Read inelastic load from file The class assumes that the file is in the current directory After the file is read, the load is inserted in the circuit and a new solution is calculated Parameters ---------- arg1 : str Name of the file Returns ------- numpy array It returns an array of P and Q tuples, for each node ''' current_directory = os.path.dirname(os.path.realpath(__file__)) pathToFile = os.path.abspath(os.path.join(current_directory, file)) if not os.path.isfile(pathToFile): print('File does not exist: ' + pathToFile) sys.exit() else: with open(pathToFile, 'r') as csvFile: csvobj = csv.reader(csvFile) data = list(csvobj) PQ = np.zeros((self._nNodes, 2)) for i in range(len(data)): nodeName = data[i][0] idx = self._terminal2node[nodeName] # If no such node in map, create one with zero load if (nodeName not in self._nodewithload.keys()): self._nodewithload[nodeName] = 0 if self._nodewithload[nodeName] > 0: PQ[idx][0] = float(data[i][1]) PQ[idx][1] = float(data[i][2]) logging.debug('New Load.' + nodeName + ' Bus1=' + nodeName + ' kW=' + data[i][1] + ' kvar=' + data[i][2]) dss.run_command('New Load.' + nodeName + ' Bus1=' + nodeName + ' kW=' + data[i][1] + ' kvar=' + data[i][2]) #-- after loading a new solution is necessary dss.Solution.Solve() return PQ
def run(self, detailed_metrics=True): """ Run the experiment. """ steps = self.horizon // self.period for t in tqdm(range(steps)): self.build_circuit() self.step_loads(t) dss.run_command("Solve") time = self.P.index[t] self.store_voltages(time) self.store_transformer_info(time) if detailed_metrics: self._summary_dict[time] = export_to_df("summary") self._overload_dict[time] = export_to_df("overload") self._capacity_dict[time] = export_to_df("capacity") self._currents_dict[time] = export_to_df("currents") self._profile_dict[time] = export_to_df("profile")
def main(): settings = ProjectModel( max_control_iterations=50, error_tolerance=0.0001, ) dss.run_command( "compile tests/data/project/DSSfiles/Master_Spohn_existing_VV.dss") volt_var_model = PvControllerModel( Control1="VVar", Control2="None", Control3="None", pf=1, pfMin=0.8, pfMax=1, Pmin=0, Pmax=1, uMin=0.9399999999999999, uDbMin=0.97, uDbMax=1.03, uMax=1.06, QlimPU=0.44, PFlim=0.9, enable_pf_limit=False, uMinC=1.06, uMaxC=1.1, PminVW=10, VWtype="Rated Power", percent_p_cutin=10, percent_p_cutout=10, Efficiency=100, Priority="Var", DampCoef=0.8, ) controller = CircuitElementController(volt_var_model) # Use all elements. manager = ControllerManager.create([controller], settings) done = False while not done: has_converged = manager.run_controls() if has_converged: print("Reached convergence") done = True else: # TODO: just an example. Real code would have other logic. raise Exception("Failed to converge")
def THD(bus_coords): ''' Calculate and plot harmonics. ''' dss.run_command('Solve mode=harmonics') dss.run_command('Export voltages voltharmonics.csv') voltHarmonics = pd.read_csv('voltharmonics.csv') bus_coords.columns = ['Bus', 'X', 'Y', 'radius'] voltHarmonics.columns.str.strip() for index, row in voltHarmonics.iterrows(): voltHarmonics['THD'] = row[' Magnitude1']/(math.sqrt(row[' Magnitude2']**2 + row[' Magnitude3']**2)) distortionDF = pd.merge(bus_coords, voltHarmonics, on='Bus') # Merge on the bus axis so that all data is in one frame. plt.scatter(distortionDF['radius'], distortionDF['THD']) plt.xlabel('Radius [m]') plt.ylabel('THD [Percentage]') plt.title('Total Harmonic Distortion') plt.savefig('THD.png') packagePlots('THD') plt.clf()
def init(self, sid, topofile, nwlfile, loadgen_interval, ilpqfile="", verbose=0): self.sid = sid self.verbose = verbose self.loadgen_interval = loadgen_interval self.swpos = 0 self.swcycle = 35 if (self.verbose > 0): print('simulator_pflow::init', self.sid) if (self.verbose > 1): print('simulator_pflow::init', topofile, nwlfile, ilpqfile, verbose) #--- start opendss self.dssObj = SimDSS(topofile, nwlfile, ilpqfile) if (self.verbose > 2): self.dssObj.showLoads() self.dssObj.showVNodes() self.dssObj.showIinout() self.dssObj.showVMagAnglePu() dss.run_command("Show Voltages LN nodes") dss.run_command("Show Buses") #--- Generate and save AdjMatrix and YMatrix # self.dssObj.createAdjMatrix("config/IEEE33_AdjMatrixFull.txt") # YMatrix = self.dssObj.getYMatrix() # np.save('config/IEEE33_YMatrixFull.npy', YMatrix) #--- create instance of LoadGenerator self.objLoadGen = LoadGenerator(nwlfile, PFLimInf=1.0, PFLimSup=1.0, LoadLimInf=0.4, LoadLimSup=0.9, AmpGain=0.25, Freq=1. / 1250, PhaseShift=math.pi) return self.meta
def currentPlots(curr_coord): ''' Current plotting function.''' dss.run_command('Export current currents.csv') current = pd.read_csv('currents.csv') curr_coord.columns = ['Index', 'X', 'Y', 'radius'] # DSS buses don't have current, but are connected to it. curr_hyp = [] currentDF = pd.concat([curr_coord, current], axis=1) for i in range(1, 3): for j in range(1, 4): cur_ind = ' I' + str(i) + '_' + str(j) plt.scatter(currentDF['radius'], currentDF[cur_ind]) plt.xlabel('Distance from source [km]') plt.ylabel('Current [Amps]') plt.title('Current profile for ' + cur_ind) plt.savefig('Profile ' + str(i) +'.png') plt.clf() packagePlots('currentPlots') plt.clf()
def networkPlot(filePath): ''' Plot the physical topology of the circuit. ''' dssFileLoc = os.path.dirname(os.path.abspath(filePath)) coords = runDSS(filePath) dss.run_command('Export voltages ' + dssFileLoc + '/volts.csv') volts = pd.read_csv(dssFileLoc + '/volts.csv') coords.columns = ['Bus', 'X', 'Y', 'radius'] G = nx.Graph() # Get the coordinates. pos = {} for index, row in coords.iterrows(): try: bus_name = str(int(row['Bus'])) except: bus_name = row['Bus'] G.add_node(bus_name) pos[bus_name] = (row['X'], row['Y']) # Get the connecting edges using Pandas. lines = dss.utils.lines_to_dataframe() edges = [] for index, row in lines.iterrows(): #HACK: dss upercases everything in the outputs. bus1 = row['Bus1'][:4].upper().replace('.', '') bus2 = row['Bus2'][:4].upper().replace('.', '') edges.append((bus1, bus2)) G.add_edges_from(edges) # We'll color the nodes according to voltage. volt_values = {} labels = {} for index, row in volts.iterrows(): volt_values[row['Bus']] = row[' pu1'] labels[row['Bus']] = row['Bus'] colorCode = [volt_values.get(node, 0.0) for node in G.nodes()] # Start drawing. nodes = nx.draw_networkx_nodes(G, pos, node_color=colorCode) edges = nx.draw_networkx_edges(G, pos) nx.draw_networkx_labels(G, pos, labels, font_size=8) plt.colorbar(nodes) plt.xlabel('Distance [m]') plt.title('Network Voltage Layout') plt.savefig(dssFileLoc + '/networkPlot.png') plt.clf()
def setLoads(self, ePQ): ''' Update circuit state with new set of loads. Add new load set to the inelastic loads Parameters ---------- arg1 : numpy array Array with <nodeName, P, Q> tuples for each node in the system ''' #-- for each load record received for i in range(len(ePQ)): #-- extract the node nodeName = ePQ[i][0] #-- find the index according to terminal2node map idx = self._terminal2node[nodeName] #-- if the number of homes in the load is greater than zero if self._nodewithload[nodeName] > 0: if (self._hasIPQ == True): logging.debug('New Load.' + nodeName + ' Bus1=' + nodeName + ' kW=' + str(self._iPQ[idx][0] + ePQ[i][1]) + ' kvar=' + str(self._iPQ[idx][1] + ePQ[i][2])) dss.run_command('New Load.' + nodeName + ' Bus1=' + nodeName + ' kW=' + str(self._iPQ[idx][0] + ePQ[i][1]) + ' kvar=' + str(self._iPQ[idx][1] + ePQ[i][2])) else: logging.debug('New Load.' + nodeName + ' Bus1=' + nodeName + ' kW=' + str(ePQ[i][1]) + ' kvar=' + str(ePQ[i][2])) dss.run_command('New Load.' + nodeName + ' Bus1=' + nodeName + ' kW=' + str(ePQ[i][1]) + ' kvar=' + str(ePQ[i][2])) #-- after setting a new load, a new system state has to be calculated self._updateSystemState()
def DSS_lines_2ph(iline, timestep): # Helper function for DSS_lines Zmat = iline.R + 1j * iline.X if Zmat[0][1] > 1e-7: Rtemp = iline.R[0:2][:, 0:2] Xtemp = iline.X[0:2][:, 0:2] elif Zmat[1][2] > 1e-7: Rtemp = iline.R[1:3][:, 1:3] Xtemp = iline.X[1:3][:, 1:3] elif Zmat[0][2] > 1e-7: Rtemp = np.array([[iline.R[0][0], iline.R[0][2]], [iline.R[2][0], iline.R[2][2]]]) Xtemp = np.array([[iline.X[0][0], iline.X[0][2]], [iline.X[2][0], iline.X[2][2]]]) r11 = Rtemp[0, 0] r12 = Rtemp[1, 0] r22 = Rtemp[1, 1] x11 = Xtemp[0, 0] x12 = Xtemp[1, 0] x22 = Xtemp[1, 1] phasestr = "." if iline.phasevec[0, 0] == 1: phasestr = phasestr + "1." if iline.phasevec[1, 0] == 1: phasestr = phasestr + "2." if iline.phasevec[2, 0] == 1: phasestr = phasestr + "3." if phasestr[len(phasestr) - 1] == ".": phasestr = phasestr[:-1] dss.run_command("New Line." + iline.name + " Bus1=" + iline.from_node.name + phasestr + " Bus2=" + iline.to_node.name + phasestr + " BaseFreq=60 Phases=2" + " rmatrix = (" + str(r11) + " | " + str(r12) + " " + str(r22) + ")" + " xmatrix = (" + str(x11) + " | " + str(x12) + " " + str(x22) + ")") return
def dynamicPlot(filePath, time_step, iterations): ''' Do a dynamic, long-term study of the powerflow. time_step is in seconds. ''' dssFileLoc = os.path.dirname(os.path.abspath(filePath)) runDSS(filePath) dss.run_command('Solve') dynamicCommand = 'Solve mode=dynamics stepsize=%d number=%d' % (time_step, iterations) dss.run_command(dynamicCommand) for i in range(iterations): voltString = 'Export voltages ' + dssFileLoc + '/dynamicVolt%d.csv' % i currentString = 'Export currents ' + dssFileLoc + '/dynamicCurrent%d.csv' % i dss.run_command(voltString) dss.run_command(currentString) powerData = [] for j in range(iterations): curVolt = 'dynamicvolt%d.csv' % j curCurrent = 'dynamiccurrent%d.csv' % j voltProfile = pd.read_csv(dssFileLoc + '/' + curVolt) voltProfile.columns = voltProfile.columns.str.replace(' ', '') curProfile = pd.read_csv(dssFileLoc + '/' + curCurrent) curProfile.columns = curProfile.columns.str.replace(' ', '') sourceVoltage = voltProfile.loc[voltProfile['Bus'] == 'SOURCEBUS'] sourceCurrent = curProfile.loc[curProfile['Element'] == 'Vsource.SOURCE'] data_summary = { 'Volts': (sourceVoltage['Magnitude1'], sourceVoltage['Magnitude2'], sourceVoltage['Magnitude3']), 'Currents': (sourceCurrent['I1_1'], sourceCurrent['I1_2'], sourceCurrent['I1_3']) } power_triplet = (data_summary['Volts'][0] * data_summary['Currents'][0], data_summary['Volts'][1] * data_summary['Currents'][1], data_summary['Volts'][2] * data_summary['Currents'][2]) powerData.append(power_triplet) first_phase = [item[0] for item in powerData] second_phase = [item[1] for item in powerData] third_phase = [item[2] for item in powerData] plt.plot(first_phase, label='Phase one') plt.plot(second_phase, label='Phase two') plt.plot(third_phase, label='Phase three') plt.legend() plt.xlim(0, iterations - 1) plt.xlabel('Time [s]') plt.ylabel('Power [kW]') plt.title('Dynamic Simulation Power Plot') plt.savefig(dssFileLoc + '/DynamicPowerPlot.png') os.system('rm ' + dssFileLoc + '/dynamicvolt* ' + dssFileLoc + '/dynamiccurrent*')
def volt_var(self): # Setting XY curve for PV volt_var yarray = [str(el) for el in self.config_dict['volt_var']['yarray']] xarray = [str(el) for el in self.config_dict['volt_var']['xarray']] assert len(xarray) == len(yarray), 'length of xarray and yarray must be same !!' self.dss_instance.run_command(f"New XYCurve.vv_curve npts={len(xarray)}" \ + " Yarray=(" + ','.join(yarray) + ") Xarray=(" + ','.join(xarray) +")") # Increment PVSystem flag = self.dss_instance.PVsystems.First() while flag>0: pv_name = self.dss_instance.PVsystems.Name() dss.run_command(f"New InvControl.InvPVCtrl_{pv_name} PVSystemList={pv_name} mode=VOLTVAR voltage_curvex_ref=rated " "vvc_curve1=vv_curve deltaQ_factor=0.08 varchangetolerance=0.00025 voltagechangetolerance=0.00001 " "Eventlog=No VV_RefReactivePower=VARMAX_VARS") flag = self.dss_instance.PVsystems.Next()
def currentPlot(filePath): ''' Current plotting function.''' dssFileLoc = os.path.dirname(os.path.abspath(filePath)) curr_coord = runDSS(filePath) dss.run_command('Export currents ' + dssFileLoc + '/currents.csv') current = pd.read_csv(dssFileLoc + '/currents.csv') curr_coord.columns = [ 'Index', 'X', 'Y', 'radius' ] # DSS buses don't have current, but are connected to it. curr_hyp = [] currentDF = pd.concat([curr_coord, current], axis=1) plt.xlabel('Distance from source [km]') plt.ylabel('Current [Amps]') plt.title('Current Profile') for i in range(1, 3): for j in range(1, 4): cur_ind = ' I' + str(i) + '_' + str(j) plt.scatter(currentDF['radius'], currentDF[cur_ind], label=cur_ind) plt.legend() plt.savefig(dssFileLoc + '/Current Profile.png') plt.clf()
def DSS_actuators(feeder, timestep): # Uses DSS commands to add the previously solved-for values of actuator dispatch to the model as negative loads. for key, iact in feeder.actdict.items(): Pvec = -iact.Pgen[:, timestep].value #print('P:',Pvec) #jasper Qvec = -iact.Qgen[:, timestep].value #print('Q:',Qvec) #jasper for idx in range(0, 3): if iact.phasevec[0, 0] == 1: dss.run_command("New Load." + iact.name + "a Bus1=" + iact.node.name + ".1 Phases=1 Conn=Wye Model=1 kV=" + str(iact.node.kVbase_phg) + " kW=" + str(Pvec[0] * iact.node.kVAbase) + " kvar=" + str(Qvec[0] * iact.node.kVAbase) + " Vminpu=0.8 Vmaxpu=1.2") if iact.phasevec[1, 0] == 1: dss.run_command("New Load." + iact.name + "b Bus1=" + iact.node.name + ".2 Phases=1 Conn=Wye Model=1 kV=" + str(iact.node.kVbase_phg) + " kW=" + str(Pvec[1] * iact.node.kVAbase) + " kvar=" + str(Qvec[1] * iact.node.kVAbase) + " Vminpu=0.8 Vmaxpu=1.2") if iact.phasevec[2, 0] == 1: dss.run_command("New Load." + iact.name + "c Bus1=" + iact.node.name + ".3 Phases=1 Conn=Wye Model=1 kV=" + str(iact.node.kVbase_phg) + " kW=" + str(Pvec[2] * iact.node.kVAbase) + " kvar=" + str(Qvec[2] * iact.node.kVAbase) + " Vminpu=0.8 Vmaxpu=1.2") return
def capacityPlot(filePath): ''' Plot power vs. distance ''' dssFileLoc = os.path.dirname(os.path.abspath(filePath)) coords = runDSS(filePath) dss.run_command('Export Capacity ' + dssFileLoc + '/capacity.csv') capacityData = pd.read_csv(dssFileLoc + '/capacity.csv') coords.columns = ['Index', 'X', 'Y', 'radius'] capacityDF = pd.concat([coords, capacityData], axis=1) fig, ax1 = plt.subplots() ax1.set_xlabel('Distance From Source [Miles]') ax1.set_ylabel('Power [kW]') ax1.scatter(capacityDF['radius'], capacityData[' kW'], label='Power') ax2 = ax1.twinx() ax2.set_ylabel('Maximum transformer percentage (One-side)') ax2.scatter(capacityDF['radius'], capacityDF.iloc[:, 2] + capacityDF.iloc[:, 3], label='Transformer Loading', color='red') fig.tight_layout() # otherwise the right y-label is slightly clipped fig.legend() plt.savefig(dssFileLoc + '/Capacity Profile.png') plt.clf()
def DSSrunsnap(dss, show=False): dss.run_command('set mode=snap') dss.run_command('Solve') if show == True: dss.run_command('show Powers kva Elements') return dss
def capacityPlot(coords): ''' Plot power vs. distance ''' dss.run_command('Export Capacity capacity.csv') capacityData = pd.read_csv('capacity.csv') coords.columns = ['Index', 'X', 'Y', 'radius'] capacityDF = pd.concat([coords, capacityData], axis=1) plt.scatter(capacityDF['radius'], capacityData[' kW']) plt.xlabel('Distance [m]') plt.ylabel('Power [kW]') plt.savefig('PowerLoad.png') plt.clf() plt.scatter(capacityDF['radius'], capacityData[' Imax']) plt.xlabel('Distance [m]') plt.ylabel('Current [Amps]') plt.savefig('CurrentLoad.png') plt.clf() plt.scatter(capacityDF['radius'], capacityDF.iloc[:, 2] + capacityDF.iloc[:, 3]) plt.xlabel('Distance [m]') plt.ylabel('Maximum transformer percentage (One-side)') plt.savefig('CurrentLoad.png') plt.clf() packagePlots('capacityPlots')