Пример #1
0
def convertTests():
    ''' Test convert every windmil feeder we have (in uploads). Return number of exceptions we hit. '''
    exceptionCount = 0
    testFiles = [('OrvilleTreePond.std', 'OrvilleTreePond.seq')]
    # ,('OlinBarre.std','OlinBarre.seq'),('OlinBeckenham.std','OlinBeckenham.seq'), ('AutocliAlberich.std','AutocliAlberich.seq')
    for stdString, seqString in testFiles:
        try:
            # Convert the std+seq.
            with open(stdString, 'r') as stdFile, open(seqString,
                                                       'r') as seqFile:
                outGlm, x, y = milToGridlab.convert(stdFile.read(),
                                                    seqFile.read())
            with open(stdString.replace('.std', '.glm'), 'w') as outFile:
                outFile.write(feeder.sortedWrite(outGlm))
            print 'WROTE GLM FOR', stdString
            try:
                # Draw the GLM.
                myGraph = feeder.treeToNxGraph(outGlm)
                feeder.latLonNxGraph(myGraph, neatoLayout=False)
                plt.savefig(stdString.replace('.std', '.png'))
                print 'DREW GLM OF', stdString
            except:
                exceptionCount += 1
                print 'FAILED DRAWING', stdString
            try:
                # Run powerflow on the GLM.
                output = gridlabd.runInFilesystem(outGlm, keepFiles=False)
                with open(stdString.replace('.std', '.json'), 'w') as outFile:
                    json.dump(output, outFile, indent=4)
                print 'RAN GRIDLAB ON', stdString
            except:
                exceptionCount += 1
                print 'POWERFLOW FAILED', stdString
        except:
            print 'FAILED CONVERTING', stdString
            exceptionCount += 1
            traceback.print_exc()
    print exceptionCount
Пример #2
0
def _tests():
    pathPrefix = '../../uploads/'
    testFiles = [
        ('INEC-RENOIR.std', 'INEC.seq'), ('INEC-GRAHAM.std', 'INEC.seq'),
        ('Olin-Barre.std', 'Olin.seq'), ('Olin-Brown.std', 'Olin.seq'),
        ('ABEC-Frank.std', 'ABEC.seq'), ('ABEC-COLUMBIA.std', 'ABEC.seq')
    ]

    for stdPath, seqPath in testFiles:
        try:
            # Conver the std+seq.
            with open(pathPrefix + stdPath,
                      'r') as stdFile, open(pathPrefix + seqPath,
                                            'r') as seqFile:
                outGlm, x, y = m2g.convert(stdFile.read(), seqFile.read())
            with open(stdPath.replace('.std', '.glm'), 'w') as outFile:
                outFile.write(feeder.sortedWrite(outGlm))
            print 'WROTE GLM FOR', stdPath
            try:
                # Draw the GLM.
                myGraph = feeder.treeToNxGraph(outGlm)
                feeder.latLonNxGraph(myGraph, neatoLayout=False)
                plt.savefig(stdPath.replace('.std', '.png'))
            except:
                print 'FAILED DRAWING', stdPath
            try:
                # Run powerflow on the GLM.
                output = gridlabd.runInFilesystem(outGlm, keepFiles=False)
                with open(stdPath.replace('.std', '.json'), 'w') as outFile:
                    json.dump(output, outFile, indent=4)
            except:
                print 'POWERFLOW FAILED', stdPath
        except:
            print 'FAILED CONVERTING', stdPath
            traceback.print_exc()

    print os.listdir('.')
Пример #3
0
def convertTests():
	''' Test convert every windmil feeder we have (in uploads). Return number of exceptions we hit. '''
	exceptionCount = 0
	testFiles = [('OrvilleTreePond.std','OrvilleTreePond.seq')]
	# ,('OlinBarre.std','OlinBarre.seq'),('OlinBeckenham.std','OlinBeckenham.seq'), ('AutocliAlberich.std','AutocliAlberich.seq')
	for stdString, seqString in testFiles:
		try:
			# Convert the std+seq.
			with open(stdString,'r') as stdFile, open(seqString,'r') as seqFile:
				outGlm,x,y = milToGridlab.convert(stdFile.read(),seqFile.read())
			with open(stdString.replace('.std','.glm'),'w') as outFile:
				outFile.write(feeder.sortedWrite(outGlm))
			print 'WROTE GLM FOR', stdString
			try:
				# Draw the GLM.
				myGraph = feeder.treeToNxGraph(outGlm)
				feeder.latLonNxGraph(myGraph, neatoLayout=False)
				plt.savefig(stdString.replace('.std','.png'))
				print 'DREW GLM OF', stdString
			except:
				exceptionCount += 1
				print 'FAILED DRAWING', stdString
			try:
				# Run powerflow on the GLM.
				output = gridlabd.runInFilesystem(outGlm, keepFiles=False)
				with open(stdString.replace('.std','.json'),'w') as outFile:
					json.dump(output, outFile, indent=4)
				print 'RAN GRIDLAB ON', stdString					
			except:
				exceptionCount += 1
				print 'POWERFLOW FAILED', stdString
		except:
			print 'FAILED CONVERTING', stdString
			exceptionCount += 1
			traceback.print_exc()
	print exceptionCount
Пример #4
0
def runForeground(modelDir, inputDict):
	''' Run the model in the foreground. WARNING: can take about a minute. '''
	# Global vars, and load data from the model directory.
	print "STARTING TO RUN", modelDir
	try:
		startTime = datetime.datetime.now()
		if not os.path.isdir(modelDir):
			os.makedirs(modelDir)
			inputDict["created"] = str(startTime)
		feederName = inputDict.get('feederName1','feeder1')
		feederPath = pJoin(modelDir,feederName+'.omd')
		feederJson = json.load(open(feederPath))
		tree = feederJson.get("tree",{})
		attachments = feederJson.get("attachments",{})
		allOutput = {}
		''' Run CVR analysis. '''
		# Reformate monthData and rates.
		rates = {k:float(inputDict[k]) for k in ["capitalCost", "omCost", "wholesaleEnergyCostPerKwh",
			"retailEnergyCostPerKwh", "peakDemandCostSpringPerKw", "peakDemandCostSummerPerKw",
			"peakDemandCostFallPerKw", "peakDemandCostWinterPerKw"]}
		# print "RATES", rates
		monthNames = ["January", "February", "March", "April", "May", "June", "July", "August",
			"September", "October", "November", "December"]
		monthToSeason = {'January':'Winter','February':'Winter','March':'Spring','April':'Spring',
			'May':'Spring','June':'Summer','July':'Summer','August':'Summer',
			'September':'Fall','October':'Fall','November':'Fall','December':'Winter'}
		monthData = []
		for i, x in enumerate(monthNames):
			monShort = x[0:3].lower()
			season = monthToSeason[x]
			histAvg = float(inputDict.get(monShort + "Avg", 0))
			histPeak = float(inputDict.get(monShort + "Peak", 0))
			monthData.append({"monthId":i, "monthName":x, "histAverage":histAvg,
				"histPeak":histPeak, "season":season})
		# for row in monthData:
		# 	print row
		# Graph the SCADA data.
		fig = plt.figure(figsize=(10,6))
		indices = [r['monthName'] for r in monthData]
		d1 = [r['histPeak']/(10**3) for r in monthData]
		d2 = [r['histAverage']/(10**3) for r in monthData]
		ticks = range(len(d1))
		bar_peak = plt.bar(ticks,d1,color='gray')
		bar_avg = plt.bar(ticks,d2,color='dimgray')
		plt.legend([bar_peak[0],bar_avg[0]],['histPeak','histAverage'],bbox_to_anchor=(0., 1.015, 1., .102), loc=3,
		   ncol=2, mode="expand", borderaxespad=0.1)
		plt.xticks([t+0.5 for t in ticks],indices)
		plt.ylabel('Mean and peak historical power consumptions (kW)')
		fig.autofmt_xdate()
		plt.savefig(pJoin(modelDir,"scadaChart.png"))
		allOutput["histPeak"] = d1
		allOutput["histAverage"] = d2
		allOutput["monthName"] = [name[0:3] for name in monthNames]
		# Graph feeder.
		fig = plt.figure(figsize=(10,10))
		myGraph = feeder.treeToNxGraph(tree)
		feeder.latLonNxGraph(myGraph, neatoLayout=False)
		plt.savefig(pJoin(modelDir,"feederChart.png"))
		with open(pJoin(modelDir,"feederChart.png"),"rb") as inFile:
			allOutput["feederChart"] = inFile.read().encode("base64")
		# Get the load levels we need to test.
		allLoadLevels = [x.get('histPeak',0) for x in monthData] + [y.get('histAverage',0) for y in monthData]
		maxLev = _roundOne(max(allLoadLevels),'up')
		minLev = _roundOne(min(allLoadLevels),'down')
		tenLoadLevels = range(int(minLev),int(maxLev),int((maxLev-minLev)/10))
		# Gather variables from the feeder.
		for key in tree.keys():
			# Set clock to single timestep.
			if tree[key].get('clock','') == 'clock':
				tree[key] = {"timezone":"PST+8PDT",
					"stoptime":"'2013-01-01 00:00:00'",
					"starttime":"'2013-01-01 00:00:00'",
					"clock":"clock"}
			# Save swing node index.
			if tree[key].get('bustype','').lower() == 'swing':
				swingIndex = key
				swingName = tree[key].get('name')
			# Remove all includes.
			if tree[key].get('omftype','') == '#include':
				del key
		# Find the substation regulator and config.
		for key in tree:
			if tree[key].get('object','') == 'regulator' and tree[key].get('from','') == swingName:
				regIndex = key
				regConfName = tree[key]['configuration']
		if not regConfName: regConfName = False
		for key in tree:
			if tree[key].get('name','') == regConfName:
				regConfIndex = key
		# Set substation regulator to manual operation.
		baselineTap = int(inputDict.get("baselineTap")) # GLOBAL VARIABLE FOR DEFAULT TAP POSITION
		tree[regConfIndex] = {
			'name':tree[regConfIndex]['name'],
			'object':'regulator_configuration',
			'connect_type':'1',
			'raise_taps':'10',
			'lower_taps':'10',
			'CT_phase':'ABC',
			'PT_phase':'ABC',
			'regulation':'0.10', #Yo, 0.10 means at tap_pos 10 we're 10% above 120V.
			'Control':'MANUAL',
			'control_level':'INDIVIDUAL',
			'Type':'A',
			'tap_pos_A':str(baselineTap),
			'tap_pos_B':str(baselineTap),
			'tap_pos_C':str(baselineTap) }
		# Attach recorders relevant to CVR.
		recorders = [
			{'object': 'collector',
			'file': 'ZlossesTransformer.csv',
			'group': 'class=transformer',
			'limit': '0',
			'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
			{'object': 'collector',
			'file': 'ZlossesUnderground.csv',
			'group': 'class=underground_line',
			'limit': '0',
			'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
			{'object': 'collector',
			'file': 'ZlossesOverhead.csv',
			'group': 'class=overhead_line',
			'limit': '0',
			'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
			{'object': 'recorder',
			'file': 'Zregulator.csv',
			'limit': '0',
			'parent': tree[regIndex]['name'],
			'property': 'tap_A,tap_B,tap_C,power_in.real,power_in.imag'},
			{'object': 'collector',
			'file': 'ZvoltageJiggle.csv',
			'group': 'class=triplex_meter',
			'limit': '0',
			'property': 'min(voltage_12.mag),mean(voltage_12.mag),max(voltage_12.mag),std(voltage_12.mag)'},
			{'object': 'recorder',
			'file': 'ZsubstationTop.csv',
			'limit': '0',
			'parent': tree[swingIndex]['name'],
			'property': 'voltage_A,voltage_B,voltage_C'},
			{'object': 'recorder',
			'file': 'ZsubstationBottom.csv',
			'limit': '0',
			'parent': tree[regIndex]['to'],
			'property': 'voltage_A,voltage_B,voltage_C'} ]
		biggest = 1 + max([int(k) for k in tree.keys()])
		for index, rec in enumerate(recorders):
			tree[biggest + index] = rec
		# Change constant PF loads to ZIP loads. (See evernote for rationale about 50/50 power/impedance mix.)
		blankZipModel = {'object':'triplex_load',
			'name':'NAMEVARIABLE',
			'base_power_12':'POWERVARIABLE',
			'power_fraction_12': str(inputDict.get("p_percent")),
			'impedance_fraction_12': str(inputDict.get("z_percent")),
			'current_fraction_12': str(inputDict.get("i_percent")),
			'power_pf_12': str(inputDict.get("power_factor")), #MAYBEFIX: we can probably get this PF data from the Milsoft loads.
			'impedance_pf_12':str(inputDict.get("power_factor")),
			'current_pf_12':str(inputDict.get("power_factor")),
			'nominal_voltage':'120',
			'phases':'PHASESVARIABLE',
			'parent':'PARENTVARIABLE' }
		def powerClean(powerStr):
			''' take 3339.39+1052.29j to 3339.39 '''
			return powerStr[0:powerStr.find('+')]
		for key in tree:
			if tree[key].get('object','') == 'triplex_node':
				# Get existing variables.
				name = tree[key].get('name','')
				power = tree[key].get('power_12','')
				parent = tree[key].get('parent','')
				phases = tree[key].get('phases','')
				# Replace object and reintroduce variables.
				tree[key] = copy(blankZipModel)
				tree[key]['name'] = name
				tree[key]['base_power_12'] = powerClean(power)
				tree[key]['parent'] = parent
				tree[key]['phases'] = phases
		# Function to determine how low we can tap down in the CVR case:
		def loweringPotential(baseLine):
			''' Given a baseline end of line voltage, how many more percent can we shave off the substation voltage? '''
			''' testsWePass = [122.0,118.0,200.0,110.0] '''
			lower = int(math.floor((baseLine/114.0-1)*100)) - 1
			# If lower is negative, we can't return it because we'd be undervolting beyond what baseline already was!
			if lower < 0:
				return baselineTap
			else:
				return baselineTap - lower
		# Run all the powerflows.
		powerflows = []
		for doingCvr in [False, True]:
			# For each load level in the tenLoadLevels, run a powerflow with the load objects scaled to the level.
			for desiredLoad in tenLoadLevels:
				# Find the total load that was defined in Milsoft:
				loadList = []
				for key in tree:
					if tree[key].get('object','') == 'triplex_load':
						loadList.append(tree[key].get('base_power_12',''))
				totalLoad = sum([float(x) for x in loadList])
				# Rescale each triplex load:
				for key in tree:
					if tree[key].get('object','') == 'triplex_load':
						currentPow = float(tree[key]['base_power_12'])
						ratio = desiredLoad/totalLoad
						tree[key]['base_power_12'] = str(currentPow*ratio)
				# If we're doing CVR then lower the voltage.
				if doingCvr:
					# Find the minimum voltage we can tap down to:
					newTapPos = baselineTap
					for row in powerflows:
						if row.get('loadLevel','') == desiredLoad:
							newTapPos = loweringPotential(row.get('lowVoltage',114))
					# Tap it down to there.
					# MAYBEFIX: do each phase separately because that's how it's done in the field... Oof.
					tree[regConfIndex]['tap_pos_A'] = str(newTapPos)
					tree[regConfIndex]['tap_pos_B'] = str(newTapPos)
					tree[regConfIndex]['tap_pos_C'] = str(newTapPos)
				# Run the model through gridlab and put outputs in the table.
				output = gridlabd.runInFilesystem(tree, attachments=attachments,
					keepFiles=True, workDir=modelDir)
				os.remove(pJoin(modelDir,"PID.txt"))
				p = output['Zregulator.csv']['power_in.real'][0]
				q = output['Zregulator.csv']['power_in.imag'][0]
				s = math.sqrt(p**2+q**2)
				lossTotal = 0.0
				for device in ['ZlossesOverhead.csv','ZlossesTransformer.csv','ZlossesUnderground.csv']:
					for letter in ['A','B','C']:
						r = output[device]['sum(power_losses_' + letter + '.real)'][0]
						i = output[device]['sum(power_losses_' + letter + '.imag)'][0]
						lossTotal += math.sqrt(r**2 + i**2)
				## Entire output:
				powerflows.append({
					'doingCvr':doingCvr,
					'loadLevel':desiredLoad,
					'realPower':p,
					'powerFactor':p/s,
					'losses':lossTotal,
					'subVoltage': (
						output['ZsubstationBottom.csv']['voltage_A'][0] +
						output['ZsubstationBottom.csv']['voltage_B'][0] +
						output['ZsubstationBottom.csv']['voltage_C'][0] )/3/60,
					'lowVoltage':output['ZvoltageJiggle.csv']['min(voltage_12.mag)'][0]/2,
					'highVoltage':output['ZvoltageJiggle.csv']['max(voltage_12.mag)'][0]/2 })
		# For a given load level, find two points to interpolate on.
		def getInterpPoints(t):
			''' Find the two points we can interpolate from. '''
			''' tests pass on [tenLoadLevels[0],tenLoadLevels[5]+499,tenLoadLevels[-1]-988] '''
			loc = sorted(tenLoadLevels + [t]).index(t)
			if loc==0:
				return (tenLoadLevels[0],tenLoadLevels[1])
			elif loc>len(tenLoadLevels)-2:
				return (tenLoadLevels[-2],tenLoadLevels[-1])
			else:
				return (tenLoadLevels[loc-1],tenLoadLevels[loc+1])
		# Calculate peak reduction.
		for row in monthData:
			peak = row['histPeak']
			peakPoints = getInterpPoints(peak)
			peakTopBase = [x for x in powerflows if x.get('loadLevel','') == peakPoints[-1] and x.get('doingCvr','') == False][0]
			peakTopCvr = [x for x in powerflows if x.get('loadLevel','') == peakPoints[-1] and x.get('doingCvr','') == True][0]
			peakBottomBase = [x for x in powerflows if x.get('loadLevel','') == peakPoints[0] and x.get('doingCvr','') == False][0]
			peakBottomCvr = [x for x in powerflows if x.get('loadLevel','') == peakPoints[0] and x.get('doingCvr','') == True][0]
			# Linear interpolation so we aren't running umpteen million loadflows.
			x = (peakPoints[0],peakPoints[1])
			y = (peakTopBase['realPower'] - peakTopCvr['realPower'],
				 peakBottomBase['realPower'] - peakBottomCvr['realPower'])
			peakRed = y[0] + (y[1] - y[0]) * (peak - x[0]) / (x[1] - x[0])
			row['peakReduction'] = peakRed
		# Calculate energy reduction and loss reduction based on average load.
		for row in monthData:
			avgEnergy = row['histAverage']
			energyPoints = getInterpPoints(avgEnergy)
			avgTopBase = [x for x in powerflows if x.get('loadLevel','') == energyPoints[-1] and x.get('doingCvr','') == False][0]
			avgTopCvr = [x for x in powerflows if x.get('loadLevel','') == energyPoints[-1] and x.get('doingCvr','') == True][0]
			avgBottomBase = [x for x in powerflows if x.get('loadLevel','') == energyPoints[0] and x.get('doingCvr','') == False][0]
			avgBottomCvr = [x for x in powerflows if x.get('loadLevel','') == energyPoints[0] and x.get('doingCvr','') == True][0]
			# Linear interpolation so we aren't running umpteen million loadflows.
			x = (energyPoints[0], energyPoints[1])
			y = (avgTopBase['realPower'] - avgTopCvr['realPower'],
				avgBottomBase['realPower'] - avgBottomCvr['realPower'])
			energyRed = y[0] + (y[1] - y[0]) * (avgEnergy - x[0]) / (x[1] - x[0])
			row['energyReduction'] = energyRed
			lossY = (avgTopBase['losses'] - avgTopCvr['losses'],
				avgBottomBase['losses'] - avgBottomCvr['losses'])
			lossRed = lossY[0] + (lossY[1] - lossY[0]) * (avgEnergy - x[0]) / (x[1] - x[0])
			row['lossReduction'] = lossRed
		# Multiply by dollars.
		for row in monthData:
			row['energyReductionDollars'] = row['energyReduction']/1000 * (rates['wholesaleEnergyCostPerKwh'] - rates['retailEnergyCostPerKwh'])
			row['peakReductionDollars'] = row['peakReduction']/1000 * rates['peakDemandCost' + row['season'] + 'PerKw']
			row['lossReductionDollars'] = row['lossReduction']/1000 * rates['wholesaleEnergyCostPerKwh']
		# Pretty output
		def plotTable(inData):
			fig = plt.figure(figsize=(10,5))
			plt.axis('off')
			plt.tight_layout()
			plt.table(cellText=[row for row in inData[1:]],
				loc = 'center',
				rowLabels = range(len(inData)-1),
				colLabels = inData[0])
		def dictalToMatrix(dictList):
			''' Take our dictal format to a matrix. '''
			matrix = [dictList[0].keys()]
			for row in dictList:
				matrix.append(row.values())
			return matrix
		# Powerflow results.
		plotTable(dictalToMatrix(powerflows))
		plt.savefig(pJoin(modelDir,"powerflowTable.png"))
		# Monetary results.
		## To print partial money table
		monthDataMat = dictalToMatrix(monthData)
		dimX = len(monthDataMat)
		dimY = len(monthDataMat[0])
		monthDataPart = []
		for k in range (0,dimX):
			monthDatatemp = []
			for m in range (4,dimY):
				monthDatatemp.append(monthDataMat[k][m])
			monthDataPart.append(monthDatatemp)

		plotTable(monthDataPart)
		plt.savefig(pJoin(modelDir,"moneyTable.png"))
		allOutput["monthDataMat"] = dictalToMatrix(monthData)
		allOutput["monthDataPart"] = monthDataPart
		# Graph the money data.
		fig = plt.figure(figsize=(10,8))
		indices = [r['monthName'] for r in monthData]
		d1 = [r['energyReductionDollars'] for r in monthData]
		d2 = [r['lossReductionDollars'] for r in monthData]
		d3 = [r['peakReductionDollars'] for r in monthData]
		ticks = range(len(d1))
		bar_erd = plt.bar(ticks,d1,color='red')
		bar_lrd = plt.bar(ticks,d2,color='green')
		bar_prd = plt.bar(ticks,d3,color='blue',yerr=d2)
		plt.legend([bar_prd[0], bar_lrd[0], bar_erd[0]], ['peakReductionDollars','lossReductionDollars','energyReductionDollars'],bbox_to_anchor=(0., 1.015, 1., .102), loc=3,
		   ncol=2, mode="expand", borderaxespad=0.1)
		plt.xticks([t+0.5 for t in ticks],indices)
		plt.ylabel('Utility Savings ($)')
		plt.tight_layout(5.5,1.3,1.2)
		fig.autofmt_xdate()
		plt.savefig(pJoin(modelDir,"spendChart.png"))
		allOutput["energyReductionDollars"] = d1
		allOutput["lossReductionDollars"] = d2
		allOutput["peakReductionDollars"] = d3
		# Graph the cumulative savings.
		fig = plt.figure(figsize=(10,5))
		annualSavings = sum(d1) + sum(d2) + sum(d3)
		annualSave = lambda x:(annualSavings - rates['omCost']) * x - rates['capitalCost']
		simplePayback = rates['capitalCost']/(annualSavings - rates['omCost'])
		plt.xlabel('Year After Installation')
		plt.xlim(0,30)
		plt.ylabel('Cumulative Savings ($)')
		plt.plot([0 for x in range(31)],c='gray')
		plt.axvline(x=simplePayback, ymin=0, ymax=1, c='gray', linestyle='--')
		plt.plot([annualSave(x) for x in range(31)], c='green')
		plt.savefig(pJoin(modelDir,"savingsChart.png"))
		allOutput["annualSave"] = [annualSave(x) for x in range(31)]
		# Update the runTime in the input file.
		endTime = datetime.datetime.now()
		inputDict["runTime"] = str(datetime.timedelta(seconds=int((endTime - startTime).total_seconds())))
		with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
			json.dump(inputDict, inFile, indent=4)
		# Write output file.
		with open(pJoin(modelDir,"allOutputData.json"),"w") as outFile:
			json.dump(allOutput, outFile, indent=4)
		# For autotest, there won't be such file.
		try:
			os.remove(pJoin(modelDir, "PPID.txt"))
		except:
			pass
		print "DONE RUNNING", modelDir
	except Exception as e:
		# If input range wasn't valid delete output, write error to disk.
		cancel(modelDir)
		thisErr = traceback.format_exc()
		print 'ERROR IN MODEL', modelDir, thisErr
		inputDict['stderr'] = thisErr
		with open(os.path.join(modelDir,'stderr.txt'),'w') as errorFile:
			errorFile.write(thisErr)
		with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
			json.dump(inputDict, inFile, indent=4)
Пример #5
0
def runForeground(modelDir, inputDict):
	''' Run the model in the foreground. WARNING: can take about a minute. '''
	# Global vars, and load data from the model directory.
	print "STARTING TO RUN", modelDir
	try:
		startTime = datetime.datetime.now()
		if not os.path.isdir(modelDir):
			os.makedirs(modelDir)
			inputDict["created"] = str(startTime)
		feederPath = pJoin(__metaModel__._omfDir,"data", "Feeder", inputDict["feederName"].split("___")[0], inputDict["feederName"].split("___")[1]+'.json')		
		feederJson = json.load(open(feederPath))
		tree = feederJson.get("tree",{})
		attachments = feederJson.get("attachments",{})
		allOutput = {}
		''' Run CVR analysis. '''
		# Reformate monthData and rates.
		rates = {k:float(inputDict[k]) for k in ["capitalCost", "omCost", "wholesaleEnergyCostPerKwh",
			"retailEnergyCostPerKwh", "peakDemandCostSpringPerKw", "peakDemandCostSummerPerKw",
			"peakDemandCostFallPerKw", "peakDemandCostWinterPerKw"]}
		# print "RATES", rates
		monthNames = ["January", "February", "March", "April", "May", "June", "July", "August",
			"September", "October", "November", "December"]
		monthToSeason = {'January':'Winter','February':'Winter','March':'Spring','April':'Spring',
			'May':'Spring','June':'Summer','July':'Summer','August':'Summer',
			'September':'Fall','October':'Fall','November':'Fall','December':'Winter'}
		monthData = []
		for i, x in enumerate(monthNames):
			monShort = x[0:3].lower()
			season = monthToSeason[x]
			histAvg = float(inputDict.get(monShort + "Avg", 0))
			histPeak = float(inputDict.get(monShort + "Peak", 0))
			monthData.append({"monthId":i, "monthName":x, "histAverage":histAvg,
				"histPeak":histPeak, "season":season})
		# for row in monthData:
		# 	print row
		# Graph the SCADA data.
		fig = plt.figure(figsize=(10,6))
		indices = [r['monthName'] for r in monthData]
		d1 = [r['histPeak']/(10**3) for r in monthData]
		d2 = [r['histAverage']/(10**3) for r in monthData]
		ticks = range(len(d1))
		bar_peak = plt.bar(ticks,d1,color='gray')
		bar_avg = plt.bar(ticks,d2,color='dimgray')
		plt.legend([bar_peak[0],bar_avg[0]],['histPeak','histAverage'],bbox_to_anchor=(0., 1.015, 1., .102), loc=3,
	       ncol=2, mode="expand", borderaxespad=0.1)
		plt.xticks([t+0.5 for t in ticks],indices)
		plt.ylabel('Mean and peak historical power consumptions (kW)')
		fig.autofmt_xdate()
		plt.savefig(pJoin(modelDir,"scadaChart.png"))
		allOutput["histPeak"] = d1
		allOutput["histAverage"] = d2
		allOutput["monthName"] = [name[0:3] for name in monthNames]
		# Graph feeder.
		fig = plt.figure(figsize=(10,10))
		myGraph = feeder.treeToNxGraph(tree)
		feeder.latLonNxGraph(myGraph, neatoLayout=False)
		plt.savefig(pJoin(modelDir,"feederChart.png"))
		with open(pJoin(modelDir,"feederChart.png"),"rb") as inFile:
			allOutput["feederChart"] = inFile.read().encode("base64")
		# Get the load levels we need to test.
		allLoadLevels = [x.get('histPeak',0) for x in monthData] + [y.get('histAverage',0) for y in monthData]
		maxLev = _roundOne(max(allLoadLevels),'up')
		minLev = _roundOne(min(allLoadLevels),'down')
		tenLoadLevels = range(int(minLev),int(maxLev),int((maxLev-minLev)/10))
		# Gather variables from the feeder.
		for key in tree.keys():
			# Set clock to single timestep.
			if tree[key].get('clock','') == 'clock':
				tree[key] = {"timezone":"PST+8PDT",
					"stoptime":"'2013-01-01 00:00:00'",
					"starttime":"'2013-01-01 00:00:00'",
					"clock":"clock"}
			# Save swing node index.
			if tree[key].get('bustype','').lower() == 'swing':
				swingIndex = key
				swingName = tree[key].get('name')
			# Remove all includes.
			if tree[key].get('omftype','') == '#include':
				del key
		# Find the substation regulator and config.
		for key in tree:
			if tree[key].get('object','') == 'regulator' and tree[key].get('from','') == swingName:
				regIndex = key
				regConfName = tree[key]['configuration']
		if not regConfName: regConfName = False
		for key in tree:
			if tree[key].get('name','') == regConfName:
				regConfIndex = key
		# Set substation regulator to manual operation.
		baselineTap = int(inputDict.get("baselineTap")) # GLOBAL VARIABLE FOR DEFAULT TAP POSITION
		tree[regConfIndex] = {
			'name':tree[regConfIndex]['name'],
			'object':'regulator_configuration',
			'connect_type':'1',
			'raise_taps':'10',
			'lower_taps':'10',
			'CT_phase':'ABC',
			'PT_phase':'ABC',
			'regulation':'0.10', #Yo, 0.10 means at tap_pos 10 we're 10% above 120V.
			'Control':'MANUAL',
			'control_level':'INDIVIDUAL',
			'Type':'A',
			'tap_pos_A':str(baselineTap),
			'tap_pos_B':str(baselineTap),
			'tap_pos_C':str(baselineTap) }
		# Attach recorders relevant to CVR.
		recorders = [
			{'object': 'collector',
			'file': 'ZlossesTransformer.csv',
			'group': 'class=transformer',
			'limit': '0',
			'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
			{'object': 'collector',
			'file': 'ZlossesUnderground.csv',
			'group': 'class=underground_line',
			'limit': '0',
			'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
			{'object': 'collector',
			'file': 'ZlossesOverhead.csv',
			'group': 'class=overhead_line',
			'limit': '0',
			'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
			{'object': 'recorder',
			'file': 'Zregulator.csv',
			'limit': '0',
			'parent': tree[regIndex]['name'],
			'property': 'tap_A,tap_B,tap_C,power_in.real,power_in.imag'},
			{'object': 'collector',
			'file': 'ZvoltageJiggle.csv',
			'group': 'class=triplex_meter',
			'limit': '0',
			'property': 'min(voltage_12.mag),mean(voltage_12.mag),max(voltage_12.mag),std(voltage_12.mag)'},
			{'object': 'recorder',
			'file': 'ZsubstationTop.csv',
			'limit': '0',
			'parent': tree[swingIndex]['name'],
			'property': 'voltage_A,voltage_B,voltage_C'},
			{'object': 'recorder',
			'file': 'ZsubstationBottom.csv',
			'limit': '0',
			'parent': tree[regIndex]['to'],
			'property': 'voltage_A,voltage_B,voltage_C'} ]
		biggest = 1 + max([int(k) for k in tree.keys()])
		for index, rec in enumerate(recorders):
			tree[biggest + index] = rec
		# Change constant PF loads to ZIP loads. (See evernote for rationale about 50/50 power/impedance mix.)
		blankZipModel = {'object':'triplex_load',
			'name':'NAMEVARIABLE',
			'base_power_12':'POWERVARIABLE',
			'power_fraction_12': str(inputDict.get("p_percent")),  
			'impedance_fraction_12': str(inputDict.get("z_percent")),
			'current_fraction_12': str(inputDict.get("i_percent")),
			'power_pf_12': str(inputDict.get("power_factor")), #MAYBEFIX: we can probably get this PF data from the Milsoft loads.
			'impedance_pf_12':str(inputDict.get("power_factor")),
			'current_pf_12':str(inputDict.get("power_factor")),
			'nominal_voltage':'120',
			'phases':'PHASESVARIABLE',
			'parent':'PARENTVARIABLE' }
		def powerClean(powerStr):
			''' take 3339.39+1052.29j to 3339.39 '''
			return powerStr[0:powerStr.find('+')]
		for key in tree:
			if tree[key].get('object','') == 'triplex_node':
				# Get existing variables.
				name = tree[key].get('name','')
				power = tree[key].get('power_12','')
				parent = tree[key].get('parent','')
				phases = tree[key].get('phases','')
				# Replace object and reintroduce variables.
				tree[key] = copy(blankZipModel)
				tree[key]['name'] = name
				tree[key]['base_power_12'] = powerClean(power)
				tree[key]['parent'] = parent
				tree[key]['phases'] = phases
		# Function to determine how low we can tap down in the CVR case:
		def loweringPotential(baseLine):
			''' Given a baseline end of line voltage, how many more percent can we shave off the substation voltage? '''
			''' testsWePass = [122.0,118.0,200.0,110.0] '''
			lower = int(math.floor((baseLine/114.0-1)*100)) - 1
			# If lower is negative, we can't return it because we'd be undervolting beyond what baseline already was!
			if lower < 0:
				return baselineTap
			else:
				return baselineTap - lower
		# Run all the powerflows.
		powerflows = []
		for doingCvr in [False, True]:
			# For each load level in the tenLoadLevels, run a powerflow with the load objects scaled to the level.
			for desiredLoad in tenLoadLevels:
				# Find the total load that was defined in Milsoft:
				loadList = []
				for key in tree:
					if tree[key].get('object','') == 'triplex_load':
						loadList.append(tree[key].get('base_power_12',''))
				totalLoad = sum([float(x) for x in loadList])
				# Rescale each triplex load:
				for key in tree:
					if tree[key].get('object','') == 'triplex_load':
						currentPow = float(tree[key]['base_power_12'])
						ratio = desiredLoad/totalLoad
						tree[key]['base_power_12'] = str(currentPow*ratio)
				# If we're doing CVR then lower the voltage.
				if doingCvr:
					# Find the minimum voltage we can tap down to:
					newTapPos = baselineTap
					for row in powerflows:
						if row.get('loadLevel','') == desiredLoad:
							newTapPos = loweringPotential(row.get('lowVoltage',114))
					# Tap it down to there.
					# MAYBEFIX: do each phase separately because that's how it's done in the field... Oof.
					tree[regConfIndex]['tap_pos_A'] = str(newTapPos)
					tree[regConfIndex]['tap_pos_B'] = str(newTapPos)
					tree[regConfIndex]['tap_pos_C'] = str(newTapPos)
				# Run the model through gridlab and put outputs in the table.
				output = gridlabd.runInFilesystem(tree, attachments=attachments,
					keepFiles=True, workDir=modelDir)
				os.remove(pJoin(modelDir,"PID.txt"))
				p = output['Zregulator.csv']['power_in.real'][0]
				q = output['Zregulator.csv']['power_in.imag'][0]
				s = math.sqrt(p**2+q**2)
				lossTotal = 0.0
				for device in ['ZlossesOverhead.csv','ZlossesTransformer.csv','ZlossesUnderground.csv']:
					for letter in ['A','B','C']:
						r = output[device]['sum(power_losses_' + letter + '.real)'][0]
						i = output[device]['sum(power_losses_' + letter + '.imag)'][0]
						lossTotal += math.sqrt(r**2 + i**2)
				## Entire output:
				powerflows.append({
					'doingCvr':doingCvr,
					'loadLevel':desiredLoad,
					'realPower':p,
					'powerFactor':p/s,
					'losses':lossTotal,
					'subVoltage': (
						output['ZsubstationBottom.csv']['voltage_A'][0] + 
						output['ZsubstationBottom.csv']['voltage_B'][0] + 
						output['ZsubstationBottom.csv']['voltage_C'][0] )/3/60,
					'lowVoltage':output['ZvoltageJiggle.csv']['min(voltage_12.mag)'][0]/2,
					'highVoltage':output['ZvoltageJiggle.csv']['max(voltage_12.mag)'][0]/2 })
		# For a given load level, find two points to interpolate on.
		def getInterpPoints(t):
			''' Find the two points we can interpolate from. '''
			''' tests pass on [tenLoadLevels[0],tenLoadLevels[5]+499,tenLoadLevels[-1]-988] '''
			loc = sorted(tenLoadLevels + [t]).index(t)
			if loc==0:
				return (tenLoadLevels[0],tenLoadLevels[1])
			elif loc>len(tenLoadLevels)-2:
				return (tenLoadLevels[-2],tenLoadLevels[-1])
			else:
				return (tenLoadLevels[loc-1],tenLoadLevels[loc+1])
		# Calculate peak reduction.
		for row in monthData:
			peak = row['histPeak']
			peakPoints = getInterpPoints(peak)
			peakTopBase = [x for x in powerflows if x.get('loadLevel','') == peakPoints[-1] and x.get('doingCvr','') == False][0]
			peakTopCvr = [x for x in powerflows if x.get('loadLevel','') == peakPoints[-1] and x.get('doingCvr','') == True][0]
			peakBottomBase = [x for x in powerflows if x.get('loadLevel','') == peakPoints[0] and x.get('doingCvr','') == False][0]
			peakBottomCvr = [x for x in powerflows if x.get('loadLevel','') == peakPoints[0] and x.get('doingCvr','') == True][0]
			# Linear interpolation so we aren't running umpteen million loadflows.
			x = (peakPoints[0],peakPoints[1])
			y = (peakTopBase['realPower'] - peakTopCvr['realPower'],
				 peakBottomBase['realPower'] - peakBottomCvr['realPower'])
			peakRed = y[0] + (y[1] - y[0]) * (peak - x[0]) / (x[1] - x[0])
			row['peakReduction'] = peakRed
		# Calculate energy reduction and loss reduction based on average load.
		for row in monthData:
			avgEnergy = row['histAverage']
			energyPoints = getInterpPoints(avgEnergy)
			avgTopBase = [x for x in powerflows if x.get('loadLevel','') == energyPoints[-1] and x.get('doingCvr','') == False][0]
			avgTopCvr = [x for x in powerflows if x.get('loadLevel','') == energyPoints[-1] and x.get('doingCvr','') == True][0]
			avgBottomBase = [x for x in powerflows if x.get('loadLevel','') == energyPoints[0] and x.get('doingCvr','') == False][0]
			avgBottomCvr = [x for x in powerflows if x.get('loadLevel','') == energyPoints[0] and x.get('doingCvr','') == True][0]
			# Linear interpolation so we aren't running umpteen million loadflows.
			x = (energyPoints[0], energyPoints[1])
			y = (avgTopBase['realPower'] - avgTopCvr['realPower'],
				avgBottomBase['realPower'] - avgBottomCvr['realPower'])
			energyRed = y[0] + (y[1] - y[0]) * (avgEnergy - x[0]) / (x[1] - x[0])
			row['energyReduction'] = energyRed
			lossY = (avgTopBase['losses'] - avgTopCvr['losses'],
				avgBottomBase['losses'] - avgBottomCvr['losses'])
			lossRed = lossY[0] + (lossY[1] - lossY[0]) * (avgEnergy - x[0]) / (x[1] - x[0])
			row['lossReduction'] = lossRed
		# Multiply by dollars.
		for row in monthData:
			row['energyReductionDollars'] = row['energyReduction']/1000 * (rates['wholesaleEnergyCostPerKwh'] - rates['retailEnergyCostPerKwh'])
			row['peakReductionDollars'] = row['peakReduction']/1000 * rates['peakDemandCost' + row['season'] + 'PerKw']
			row['lossReductionDollars'] = row['lossReduction']/1000 * rates['wholesaleEnergyCostPerKwh']
		# Pretty output
		def plotTable(inData):
			fig = plt.figure(figsize=(10,5))
			plt.axis('off')
			plt.tight_layout()
			plt.table(cellText=[row for row in inData[1:]], 
				loc = 'center',
				rowLabels = range(len(inData)-1),
				colLabels = inData[0])
		def dictalToMatrix(dictList):
			''' Take our dictal format to a matrix. '''
			matrix = [dictList[0].keys()]
			for row in dictList:
				matrix.append(row.values())
			return matrix
		# Powerflow results.
		plotTable(dictalToMatrix(powerflows))
		plt.savefig(pJoin(modelDir,"powerflowTable.png"))
		# Monetary results.
		## To print partial money table
		monthDataMat = dictalToMatrix(monthData)
		dimX = len(monthDataMat)
		dimY = len(monthDataMat[0])
		monthDataPart = []
		for k in range (0,dimX):
			monthDatatemp = []
			for m in range (4,dimY):
				monthDatatemp.append(monthDataMat[k][m])
			monthDataPart.append(monthDatatemp)

		plotTable(monthDataPart)
		plt.savefig(pJoin(modelDir,"moneyTable.png"))
		allOutput["monthDataMat"] = dictalToMatrix(monthData)
		allOutput["monthDataPart"] = monthDataPart
		# Graph the money data.
		fig = plt.figure(figsize=(10,8))
		indices = [r['monthName'] for r in monthData]
		d1 = [r['energyReductionDollars'] for r in monthData]
		d2 = [r['lossReductionDollars'] for r in monthData]
		d3 = [r['peakReductionDollars'] for r in monthData]
		ticks = range(len(d1))
		bar_erd = plt.bar(ticks,d1,color='red')
		bar_lrd = plt.bar(ticks,d2,color='green')
		bar_prd = plt.bar(ticks,d3,color='blue',yerr=d2)
		plt.legend([bar_prd[0], bar_lrd[0], bar_erd[0]], ['peakReductionDollars','lossReductionDollars','energyReductionDollars'],bbox_to_anchor=(0., 1.015, 1., .102), loc=3,
	       ncol=2, mode="expand", borderaxespad=0.1)
		plt.xticks([t+0.5 for t in ticks],indices)
		plt.ylabel('Utility Savings ($)')
		plt.tight_layout(5.5,1.3,1.2)
		fig.autofmt_xdate()
		plt.savefig(pJoin(modelDir,"spendChart.png"))
		allOutput["energyReductionDollars"] = d1
		allOutput["lossReductionDollars"] = d2
		allOutput["peakReductionDollars"] = d3
		# Graph the cumulative savings.
		fig = plt.figure(figsize=(10,5))
		annualSavings = sum(d1) + sum(d2) + sum(d3)
		annualSave = lambda x:(annualSavings - rates['omCost']) * x - rates['capitalCost']
		simplePayback = rates['capitalCost']/(annualSavings - rates['omCost'])
		plt.xlabel('Year After Installation')
		plt.xlim(0,30)
		plt.ylabel('Cumulative Savings ($)')
		plt.plot([0 for x in range(31)],c='gray')
		plt.axvline(x=simplePayback, ymin=0, ymax=1, c='gray', linestyle='--')
		plt.plot([annualSave(x) for x in range(31)], c='green')
		plt.savefig(pJoin(modelDir,"savingsChart.png"))
		allOutput["annualSave"] = [annualSave(x) for x in range(31)]
		# Update the runTime in the input file.
		endTime = datetime.datetime.now()
		inputDict["runTime"] = str(datetime.timedelta(seconds=int((endTime - startTime).total_seconds())))
		with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
			json.dump(inputDict, inFile, indent=4)
		# Write output file.
		with open(pJoin(modelDir,"allOutputData.json"),"w") as outFile:
			json.dump(allOutput, outFile, indent=4)
		# For autotest, there won't be such file.
		try:
			os.remove(pJoin(modelDir, "PPID.txt"))
		except:
			pass
		print "DONE RUNNING", modelDir
	except Exception as e:
		# If input range wasn't valid delete output, write error to disk.
		cancel(modelDir)				
		thisErr = traceback.format_exc()
		print 'ERROR IN MODEL', modelDir, thisErr
		inputDict['stderr'] = thisErr
		with open(os.path.join(modelDir,'stderr.txt'),'w') as errorFile:
			errorFile.write(thisErr)
		with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
			json.dump(inputDict, inFile, indent=4)
Пример #6
0
def voltPlot(tree, workDir=None, neatoLayout=False):
	''' Draw a color-coded map of the voltage drop on a feeder.
	Returns a matplotlib object. '''
	# Get rid of schedules and climate:
	for key in tree.keys():
		if tree[key].get("argument","") == "\"schedules.glm\"" or tree[key].get("tmyfile","") != "":
			del tree[key]
	# Make sure we have a voltDump:
	def safeInt(x):
		try: return int(x)
		except: return 0
	biggestKey = max([safeInt(x) for x in tree.keys()])
	tree[str(biggestKey*10)] = {"object":"voltdump","filename":"voltDump.csv"}
	# Run Gridlab.
	if not workDir:
		workDir = tempfile.mkdtemp()
		print "gridlabD runInFilesystem with no specified workDir. Working in", workDir
	gridlabOut = gridlabd.runInFilesystem(tree, attachments=[], workDir=workDir)
	with open(pJoin(workDir,'voltDump.csv'),'r') as dumpFile:
		reader = csv.reader(dumpFile)
		reader.next() # Burn the header.
		keys = reader.next()
		voltTable = []
		for row in reader:
			rowDict = {}
			for pos,key in enumerate(keys):
				rowDict[key] = row[pos]
			voltTable.append(rowDict)
	# Calculate average node voltage deviation. First, helper functions.
	def pythag(x,y):
		''' For right triangle with sides a and b, return the hypotenuse. '''
		return math.sqrt(x**2+y**2)
	def digits(x):
		''' Returns number of digits before the decimal in the float x. '''
		return math.ceil(math.log10(x+1))
	def avg(l):
		''' Average of a list of ints or floats. '''
		return sum(l)/len(l)
	# Detect the feeder nominal voltage:
	for key in tree:
		ob = tree[key]
		if type(ob)==dict and ob.get('bustype','')=='SWING':
			feedVoltage = float(ob.get('nominal_voltage',1))
	# Tot it all up.
	nodeVolts = {}
	for row in voltTable:
		allVolts = []
		for phase in ['A','B','C']:
			phaseVolt = pythag(float(row['volt'+phase+'_real']),
							   float(row['volt'+phase+'_imag']))
			if phaseVolt != 0.0:
				if digits(phaseVolt)>3:
					# Normalize to 120 V standard
					phaseVolt = phaseVolt*(120/feedVoltage)
				allVolts.append(phaseVolt)
		nodeVolts[row.get('node_name','')] = avg(allVolts)
	# Color nodes by VOLTAGE.
	fGraph = feeder.treeToNxGraph(tree)
	voltChart = plt.figure(figsize=(10,10))
	plt.axes(frameon = 0)
	plt.axis('off')
	if neatoLayout:
		# HACK: work on a new graph without attributes because graphViz tries to read attrs.
		cleanG = nx.Graph(fGraph.edges())
		cleanG.add_nodes_from(fGraph)
		positions = nx.graphviz_layout(cleanG, prog='neato')
	else:
		positions = {n:fGraph.node[n].get('pos',(0,0)) for n in fGraph}
	edgeIm = nx.draw_networkx_edges(fGraph, positions)
	nodeIm = nx.draw_networkx_nodes(fGraph,
		pos = positions,
		node_color = [nodeVolts.get(n,0) for n in fGraph.nodes()],
		linewidths = 0,
		node_size = 30,
		cmap = plt.cm.jet)
	plt.sci(nodeIm)
	plt.clim(110,130)
	plt.colorbar()
	return voltChart
Пример #7
0
def runAnalysis(tree, monthData, rates):
	''' Run CVR analysis. '''

	# Graph the SCADA data.
	fig = plt.figure(figsize=(17,5))
	indices = [r['monthName'] for r in monthData]
	d1 = [r['histPeak']/(10**3) for r in monthData]
	d2 = [r['histAverage']/(10**3) for r in monthData]
	ticks = range(len(d1))
	plt.bar(ticks,d1,color='gray')
	plt.bar(ticks,d2,color='dimgray')
	plt.xticks([t+0.5 for t in ticks],indices)
	plt.ylabel('Mean and peak historical power consumptions (kW)')

	# Graph feeder.
	myGraph = feeder.treeToNxGraph(tree)
	feeder.latLonNxGraph(myGraph, neatoLayout=False)

	# Get the load levels we need to test.
	allLoadLevels = [x.get('histPeak',0) for x in monthData] + [y.get('histAverage',0) for y in monthData]
	maxLev = _roundOne(max(allLoadLevels),'up')
	minLev = _roundOne(min(allLoadLevels),'down')
	tenLoadLevels = range(int(minLev),int(maxLev),int((maxLev-minLev)/10))

	# Gather variables from the feeder.
	for key in tree.keys():
		# Set clock to single timestep.
		if tree[key].get('clock','') == 'clock':
			tree[key] = {"timezone":"PST+8PDT",
				"stoptime":"'2013-01-01 00:00:00'",
				"starttime":"'2013-01-01 00:00:00'",
				"clock":"clock"}
		# Save swing node index.
		if tree[key].get('bustype','').lower() == 'swing':
			swingIndex = key
			swingName = tree[key].get('name')
		# Remove all includes.
		if tree[key].get('omftype','') == '#include':
			del key

	# Find the substation regulator and config.
	for key in tree:
		if tree[key].get('object','') == 'regulator' and tree[key].get('from','') == swingName:
			regIndex = key
			regConfName = tree[key]['configuration']
	for key in tree:
		if tree[key].get('name','') == regConfName:
			regConfIndex = key

	# Set substation regulator to manual operation.
	baselineTap = 3 # GLOBAL VARIABLE FOR DEFAULT TAP POSITION
	tree[regConfIndex] = {
		'name':tree[regConfIndex]['name'],
		'object':'regulator_configuration',
		'connect_type':'1',
		'raise_taps':'10',
		'lower_taps':'10',
		'CT_phase':'ABC',
		'PT_phase':'ABC',
		'regulation':'0.10', #Yo, 0.10 means at tap_pos 10 we're 10% above 120V.
		'Control':'MANUAL',
		'control_level':'INDIVIDUAL',
		'Type':'A',
		'tap_pos_A':str(baselineTap),
		'tap_pos_B':str(baselineTap),
		'tap_pos_C':str(baselineTap) }

	# Attach recorders relevant to CVR.
	recorders = [
		{'object': 'collector',
		'file': 'ZlossesTransformer.csv',
		'group': 'class=transformer',
		'limit': '0',
		'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
		{'object': 'collector',
		'file': 'ZlossesUnderground.csv',
		'group': 'class=underground_line',
		'limit': '0',
		'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
		{'object': 'collector',
		'file': 'ZlossesOverhead.csv',
		'group': 'class=overhead_line',
		'limit': '0',
		'property': 'sum(power_losses_A.real),sum(power_losses_A.imag),sum(power_losses_B.real),sum(power_losses_B.imag),sum(power_losses_C.real),sum(power_losses_C.imag)'},
		{'object': 'recorder',
		'file': 'Zregulator.csv',
		'limit': '0',
		'parent': tree[regIndex]['name'],
		'property': 'tap_A,tap_B,tap_C,power_in.real,power_in.imag'},
		{'object': 'collector',
		'file': 'ZvoltageJiggle.csv',
		'group': 'class=triplex_meter',
		'limit': '0',
		'property': 'min(voltage_12.mag),mean(voltage_12.mag),max(voltage_12.mag),std(voltage_12.mag)'},
		{'object': 'recorder',
		'file': 'ZsubstationTop.csv',
		'limit': '0',
		'parent': tree[swingIndex]['name'],
		'property': 'voltage_A,voltage_B,voltage_C'},
		{'object': 'recorder',
		'file': 'ZsubstationBottom.csv',
		'limit': '0',
		'parent': tree[regIndex]['to'],
		'property': 'voltage_A,voltage_B,voltage_C'} ]
	biggest = 1 + max([int(k) for k in tree.keys()])
	for index, rec in enumerate(recorders):
		tree[biggest + index] = rec

	# Change constant PF loads to ZIP loads. (See evernote for rationale about 50/50 power/impedance mix.)
	blankZipModel = {'object':'triplex_load',
		'name':'NAMEVARIABLE',
		'base_power_12':'POWERVARIABLE',
		'power_fraction_12':'0.5',
		'impedance_fraction_12':'0.5',
		'power_pf_12':'0.9', #TODO: we can probably get this PF data from the Milsoft loads.
		'impedance_pf_12':'0.97',
		'nominal_voltage':'120',
		'phases':'PHASESVARIABLE',
		'parent':'PARENTVARIABLE'}
	def powerClean(powerStr):
		''' take 3339.39+1052.29j to 3339.39 '''
		return powerStr[0:powerStr.find('+')]
	for key in tree:
		if tree[key].get('object','') == 'triplex_node':
			# Get existing variables.
			name = tree[key].get('name','')
			power = tree[key].get('power_12','')
			parent = tree[key].get('parent','')
			phases = tree[key].get('phases','')
			# Replace object and reintroduce variables.
			tree[key] = copy(blankZipModel)
			tree[key]['name'] = name
			tree[key]['base_power_12'] = powerClean(power)
			tree[key]['parent'] = parent
			tree[key]['phases'] = phases

	# Function to determine how low we can tap down in the CVR case:
	def loweringPotential(baseLine):
		''' Given a baseline end of line voltage, how many more percent can we shave off the substation voltage? '''
		''' testsWePass = [122.0,118.0,200.0,110.0] '''
		lower = int(math.floor((baseLine/114.0-1)*100)) - 1
		# If lower is negative, we can't return it because we'd be undervolting beyond what baseline already was!
		if lower < 0:
			return baselineTap
		else:
			return baselineTap - lower

	# Run all the powerflows.
	powerflows = []
	for doingCvr in [False, True]:
		# For each load level in the tenLoadLevels, run a powerflow with the load objects scaled to the level.
		for desiredLoad in tenLoadLevels:
			# Find the total load that was defined in Milsoft:
			loadList = []
			for key in tree:
				if tree[key].get('object','') == 'triplex_load':
					loadList.append(tree[key].get('base_power_12',''))
			totalLoad = sum([float(x) for x in loadList])
			# Rescale each triplex load:
			for key in tree:
				if tree[key].get('object','') == 'triplex_load':
					currentPow = float(tree[key]['base_power_12'])
					ratio = desiredLoad/totalLoad
					tree[key]['base_power_12'] = str(currentPow*ratio)
			# If we're doing CVR then lower the voltage.
			if doingCvr:
				# Find the minimum voltage we can tap down to:
				newTapPos = baselineTap
				for row in powerflows:
					if row.get('loadLevel','') == desiredLoad:
						newTapPos = loweringPotential(row.get('lowVoltage',114))
				# Tap it down to there.
				# TODO: do each phase separately because that's how it's done in the field... Oof.
				tree[regConfIndex]['tap_pos_A'] = str(newTapPos)
				tree[regConfIndex]['tap_pos_B'] = str(newTapPos)
				tree[regConfIndex]['tap_pos_C'] = str(newTapPos)
			# Run the model through gridlab and put outputs in the table.
			output = gridlabd.runInFilesystem(tree, keepFiles=False)
			p = output['Zregulator.csv']['power_in.real'][0]
			q = output['Zregulator.csv']['power_in.imag'][0]
			s = math.sqrt(p**2+q**2)
			lossTotal = 0.0
			for device in ['ZlossesOverhead.csv','ZlossesTransformer.csv','ZlossesUnderground.csv']:
				for letter in ['A','B','C']:
					r = output[device]['sum(power_losses_' + letter + '.real)'][0]
					i = output[device]['sum(power_losses_' + letter + '.imag)'][0]
					lossTotal += math.sqrt(r**2 + i**2)
			## Entire output:
			powerflows.append({
				'doingCvr':doingCvr,
				'loadLevel':desiredLoad,
				'realPower':p,
				'powerFactor':p/s,
				'losses':lossTotal,
				'subVoltage': (
					output['ZsubstationBottom.csv']['voltage_A'][0] + 
					output['ZsubstationBottom.csv']['voltage_B'][0] + 
					output['ZsubstationBottom.csv']['voltage_C'][0] )/3/60,
				'lowVoltage':output['ZvoltageJiggle.csv']['min(voltage_12.mag)'][0]/2,
				'highVoltage':output['ZvoltageJiggle.csv']['max(voltage_12.mag)'][0]/2 })

	# For a given load level, find two points to interpolate on.
	def getInterpPoints(t):
		''' Find the two points we can interpolate from. '''
		''' tests pass on [tenLoadLevels[0],tenLoadLevels[5]+499,tenLoadLevels[-1]-988] '''
		loc = sorted(tenLoadLevels + [t]).index(t)
		if loc==0:
			return (tenLoadLevels[0],tenLoadLevels[1])
		elif loc>len(tenLoadLevels)-2:
			return (tenLoadLevels[-2],tenLoadLevels[-1])
		else:
			return (tenLoadLevels[loc-1],tenLoadLevels[loc+1])

	# Calculate peak reduction.
	for row in monthData:
		peak = row['histPeak']
		peakPoints = getInterpPoints(peak)
		peakTopBase = [x for x in powerflows if x.get('loadLevel','') == peakPoints[-1] and x.get('doingCvr','') == False][0]
		peakTopCvr = [x for x in powerflows if x.get('loadLevel','') == peakPoints[-1] and x.get('doingCvr','') == True][0]
		peakBottomBase = [x for x in powerflows if x.get('loadLevel','') == peakPoints[0] and x.get('doingCvr','') == False][0]
		peakBottomCvr = [x for x in powerflows if x.get('loadLevel','') == peakPoints[0] and x.get('doingCvr','') == True][0]
		# Linear interpolation so we aren't running umpteen million loadflows.
		x = (peakPoints[0],peakPoints[1])
		y = (peakTopBase['realPower'] - peakTopCvr['realPower'],
			 peakBottomBase['realPower'] - peakBottomCvr['realPower'])
		peakRed = y[0] + (y[1] - y[0]) * (peak - x[0]) / (x[1] - x[0])
		row['peakReduction'] = peakRed

	# Calculate energy reduction and loss reduction based on average load.
	for row in monthData:
		avgEnergy = row['histAverage']
		energyPoints = getInterpPoints(avgEnergy)
		avgTopBase = [x for x in powerflows if x.get('loadLevel','') == energyPoints[-1] and x.get('doingCvr','') == False][0]
		avgTopCvr = [x for x in powerflows if x.get('loadLevel','') == energyPoints[-1] and x.get('doingCvr','') == True][0]
		avgBottomBase = [x for x in powerflows if x.get('loadLevel','') == energyPoints[0] and x.get('doingCvr','') == False][0]
		avgBottomCvr = [x for x in powerflows if x.get('loadLevel','') == energyPoints[0] and x.get('doingCvr','') == True][0]
		# Linear interpolation so we aren't running umpteen million loadflows.
		x = (energyPoints[0], energyPoints[1])
		y = (avgTopBase['realPower'] - avgTopCvr['realPower'],
			avgBottomBase['realPower'] - avgBottomCvr['realPower'])
		energyRed = y[0] + (y[1] - y[0]) * (avgEnergy - x[0]) / (x[1] - x[0])
		row['energyReduction'] = energyRed
		lossY = (avgTopBase['losses'] - avgTopCvr['losses'],
			avgBottomBase['losses'] - avgBottomCvr['losses'])
		lossRed = lossY[0] + (lossY[1] - lossY[0]) * (avgEnergy - x[0]) / (x[1] - x[0])
		row['lossReduction'] = lossRed

	# Multiply by dollars.
	for row in monthData:
		row['energyReductionDollars'] = row['energyReduction'] * (rates['wholesaleEnergyCostPerKwh'] - rates['retailEnergyCostPerKwh'])
		row['peakReductionDollars'] = row['peakReduction'] * rates['peakDemandCost' + row['season'] + 'PerKw']
		row['lossReductionDollars'] = row['lossReduction'] * rates['wholesaleEnergyCostPerKwh']

	# Pretty output
	def plotTable(inData):
		fig = plt.figure(figsize=(20,10))
		plt.axis('off')
		plt.tight_layout()
		plt.table(cellText=[row[1:] for row in inData[1:]], 
			loc = 'center',
			rowLabels = [row[0] for row in inData[1:]],
			colLabels = inData[0])
	def dictalToMatrix(dictList):
		''' Take our dictal format to a matrix. '''
		matrix = [dictList[0].keys()]
		for row in dictList:
			matrix.append(row.values())
		return matrix

	# Powerflow results.
	plotTable(dictalToMatrix(powerflows))

	# Monetary results.
	plotTable(dictalToMatrix(monthData))

	# Graph the money data.
	fig = plt.figure(figsize=(17,10))
	indices = [r['monthName'] for r in monthData]
	d1 = [r['energyReductionDollars'] for r in monthData]
	d2 = [r['lossReductionDollars'] for r in monthData]
	d3 = [r['peakReductionDollars'] for r in monthData]
	ticks = range(len(d1))
	plt.bar(ticks,d1,color='red')
	plt.bar(ticks,d2,color='green')
	plt.bar(ticks,d3,color='blue',yerr=d2)
	plt.xticks([t+0.5 for t in ticks],indices)
	plt.ylabel('Utility Savings ($)')

	# Graph the cumulative savings.
	fig = plt.figure(figsize=(17,8))
	annualSavings = sum(d1) + sum(d2) + sum(d3)
	annualSave = lambda x:(annualSavings - rates['omCost']) * x - rates['capitalCost']
	simplePayback = rates['capitalCost']/(annualSavings - rates['omCost'])
	plt.xlabel('Year After Installation')
	plt.xlim(0,30)
	plt.ylabel('Cumulative Savings ($)')
	plt.plot([0 for x in range(31)],c='gray')
	plt.axvline(x=simplePayback, ymin=0, ymax=1, c='gray', linestyle='--')
	plt.plot([annualSave(x) for x in range(31)], c='green')
Пример #8
0
def generateVoltChart(tree, rawOut, modelDir, neatoLayout=True):
    ''' Map the voltages on a feeder over time using a movie.'''
    # We need to timestamp frames with the system clock to make sure the browser caches them appropriately.
    genTime = str(datetime.datetime.now()).replace(':', '.')
    # Detect the feeder nominal voltage:
    for key in tree:
        ob = tree[key]
        if type(ob) == dict and ob.get('bustype', '') == 'SWING':
            feedVoltage = float(ob.get('nominal_voltage', 1))
    # Make a graph object.
    fGraph = feeder.treeToNxGraph(tree)
    if neatoLayout:
        # HACK: work on a new graph without attributes because graphViz tries to read attrs.
        cleanG = nx.Graph(fGraph.edges())
        cleanG.add_nodes_from(fGraph)
        positions = nx.graphviz_layout(cleanG, prog='neato')
    else:
        rawPositions = {n: fGraph.node[n].get('pos', (0, 0)) for n in fGraph}

        #HACK: the import code reverses the y coords.
        def yFlip(pair):
            try:
                return (pair[0], -1.0 * pair[1])
            except:
                return (0, 0)

        positions = {k: yFlip(rawPositions[k]) for k in rawPositions}
    # Plot all time steps.
    nodeVolts = {}
    for step, stamp in enumerate(rawOut['aVoltDump.csv']['# timestamp']):
        # Build voltage map.
        nodeVolts[step] = {}
        for nodeName in [
                x for x in rawOut['aVoltDump.csv'].keys() if x != '# timestamp'
        ]:
            allVolts = []
            for phase in ['a', 'b', 'c']:
                voltStep = rawOut[phase + 'VoltDump.csv'][nodeName][step]
                # HACK: Gridlab complex number format sometimes uses i, sometimes j, sometimes d. WTF?
                if type(voltStep) is str: voltStep = voltStep.replace('i', 'j')
                v = complex(voltStep)
                phaseVolt = abs(v)
                if phaseVolt != 0.0:
                    if _digits(phaseVolt) > 3:
                        # Normalize to 120 V standard
                        phaseVolt = phaseVolt * (120 / feedVoltage)
                    allVolts.append(phaseVolt)
            # HACK: Take average of all phases to collapse dimensionality.
            nodeVolts[step][nodeName] = avg(allVolts)
    # Draw animation.
    voltChart = plt.figure(figsize=(10, 10))
    plt.axes(frameon=0)
    plt.axis('off')
    voltChart.subplots_adjust(left=0.03,
                              bottom=0.03,
                              right=0.97,
                              top=0.97,
                              wspace=None,
                              hspace=None)
    custom_cm = matplotlib.colors.LinearSegmentedColormap.from_list(
        'custColMap', [(0.0, 'blue'), (0.25, 'darkgray'), (0.75, 'darkgray'),
                       (1.0, 'yellow')])
    edgeIm = nx.draw_networkx_edges(fGraph, positions)
    nodeIm = nx.draw_networkx_nodes(
        fGraph,
        pos=positions,
        node_color=[nodeVolts[0].get(n, 0) for n in fGraph.nodes()],
        linewidths=0,
        node_size=30,
        cmap=custom_cm)
    plt.sci(nodeIm)
    plt.clim(110, 130)
    plt.colorbar()
    plt.title(rawOut['aVoltDump.csv']['# timestamp'][0])

    def update(step):
        nodeColors = np.array(
            [nodeVolts[step].get(n, 0) for n in fGraph.nodes()])
        plt.title(rawOut['aVoltDump.csv']['# timestamp'][step])
        nodeIm.set_array(nodeColors)
        return nodeColors,

    anim = FuncAnimation(voltChart,
                         update,
                         frames=len(rawOut['aVoltDump.csv']['# timestamp']),
                         interval=200,
                         blit=False)
    anim.save(pJoin(modelDir, 'voltageChart.mp4'),
              codec='h264',
              extra_args=['-pix_fmt', 'yuv420p'])
    # Reclaim memory by closing, deleting and garbage collecting the last chart.
    voltChart.clf()
    plt.close()
    del voltChart
    gc.collect()
    return genTime
Пример #9
0
def _tests(Network, Equipment, keepFiles=True):
    import os, json, traceback, shutil
    from solvers import gridlabd
    from matplotlib import pyplot as plt
    import feeder
    exceptionCount = 0       
    try:
        #db_network = os.path.abspath('./uploads/IEEE13.mdb')
        #db_equipment = os.path.abspath('./uploads/IEEE13.mdb')
        prefix = str(Path("testPEC.py").resolve()).strip('scratch\cymeToGridlabTests\testPEC.py') + "\uploads\\"      
        db_network = "C" + prefix + Network
        db_equipment = "C" + prefix + Equipment
        id_feeder = '650'
        conductors = prefix + "conductor_data.csv"
        #print "dbnet", db_network
        #print "eqnet", db_equipment               
        #print "conductors", conductors
        #cyme_base, x, y = convertCymeModel(db_network, db_equipment, id_feeder, conductors)
        cyme_base, x, y = convertCymeModel(str(db_network), str(db_equipment), test=True, type=2, feeder_id='CV160')    
        feeder.attachRecorders(cyme_base, "TriplexLosses", None, None)
        feeder.attachRecorders(cyme_base, "TransformerLosses", None, None)
        glmString = feeder.sortedWrite(cyme_base)
        feederglm = "C:\Users\Asus\Documents\GitHub\omf\omf\uploads\PEC.glm"
        #print "feeederglm", feederglm
        gfile = open(feederglm, 'w')
        gfile.write(glmString)
        gfile.close()
        #print 'WROTE GLM FOR'
        outPrefix = "C:\Users\Asus\Documents\GitHub\omf\omf\scratch\cymeToGridlabTests\\"          
        try:
            os.mkdir(outPrefix)
        except:
            pass # Directory already there.     
        '''Attempt to graph'''      
        try:
            # Draw the GLM.
            print "trying to graph"
            myGraph = feeder.treeToNxGraph(cyme_base)
            feeder.latLonNxGraph(myGraph, neatoLayout=False)
            plt.savefig(outPrefix + "PEC.png")
            print "outprefix", outPrefix + "PEC.png"
            print 'DREW GLM OF'
        except:
            exceptionCount += 1
            print 'FAILED DRAWING'
        try:
            # Run powerflow on the GLM.
            output = gridlabd.runInFilesystem(glmString, keepFiles=False)
            with open(outPrefix + "PEC.JSON",'w') as outFile:
                json.dump(output, outFile, indent=4)
            print 'RAN GRIDLAB ON\n'                 
        except:
            exceptionCount += 1
            print 'POWERFLOW FAILED'
    except:
        print 'FAILED CONVERTING'
        exceptionCount += 1
        traceback.print_exc()
    if not keepFiles:
        shutil.rmtree(outPrefix)
    return exceptionCount    
    '''db_network = os.path.abspath('./uploads/PasoRobles11cymsectiondevice[device]['phases']08.mdb')
Пример #10
0
def voltPlot(tree, workDir=None, neatoLayout=False):
    ''' Draw a color-coded map of the voltage drop on a feeder.
	Returns a matplotlib object. '''
    # Get rid of schedules and climate:
    for key in tree.keys():
        if tree[key].get("argument",
                         "") == "\"schedules.glm\"" or tree[key].get(
                             "tmyfile", "") != "":
            del tree[key]
    # Make sure we have a voltDump:
    def safeInt(x):
        try:
            return int(x)
        except:
            return 0

    biggestKey = max([safeInt(x) for x in tree.keys()])
    tree[str(biggestKey * 10)] = {
        "object": "voltdump",
        "filename": "voltDump.csv"
    }
    # Run Gridlab.
    if not workDir:
        workDir = tempfile.mkdtemp()
        print "gridlabD runInFilesystem with no specified workDir. Working in", workDir
    gridlabOut = gridlabd.runInFilesystem(tree,
                                          attachments=[],
                                          workDir=workDir)
    with open(pJoin(workDir, 'voltDump.csv'), 'r') as dumpFile:
        reader = csv.reader(dumpFile)
        reader.next()  # Burn the header.
        keys = reader.next()
        voltTable = []
        for row in reader:
            rowDict = {}
            for pos, key in enumerate(keys):
                rowDict[key] = row[pos]
            voltTable.append(rowDict)
    # Calculate average node voltage deviation. First, helper functions.
    def pythag(x, y):
        ''' For right triangle with sides a and b, return the hypotenuse. '''
        return math.sqrt(x**2 + y**2)

    def digits(x):
        ''' Returns number of digits before the decimal in the float x. '''
        return math.ceil(math.log10(x + 1))

    def avg(l):
        ''' Average of a list of ints or floats. '''
        return sum(l) / len(l)

    # Detect the feeder nominal voltage:
    for key in tree:
        ob = tree[key]
        if type(ob) == dict and ob.get('bustype', '') == 'SWING':
            feedVoltage = float(ob.get('nominal_voltage', 1))
    # Tot it all up.
    nodeVolts = {}
    for row in voltTable:
        allVolts = []
        for phase in ['A', 'B', 'C']:
            phaseVolt = pythag(float(row['volt' + phase + '_real']),
                               float(row['volt' + phase + '_imag']))
            if phaseVolt != 0.0:
                if digits(phaseVolt) > 3:
                    # Normalize to 120 V standard
                    phaseVolt = phaseVolt * (120 / feedVoltage)
                allVolts.append(phaseVolt)
        nodeVolts[row.get('node_name', '')] = avg(allVolts)
    # Color nodes by VOLTAGE.
    fGraph = feeder.treeToNxGraph(tree)
    voltChart = plt.figure(figsize=(10, 10))
    plt.axes(frameon=0)
    plt.axis('off')
    if neatoLayout:
        # HACK: work on a new graph without attributes because graphViz tries to read attrs.
        cleanG = nx.Graph(fGraph.edges())
        cleanG.add_nodes_from(fGraph)
        positions = nx.graphviz_layout(cleanG, prog='neato')
    else:
        positions = {n: fGraph.node[n].get('pos', (0, 0)) for n in fGraph}
    edgeIm = nx.draw_networkx_edges(fGraph, positions)
    nodeIm = nx.draw_networkx_nodes(
        fGraph,
        pos=positions,
        node_color=[nodeVolts.get(n, 0) for n in fGraph.nodes()],
        linewidths=0,
        node_size=30,
        cmap=plt.cm.jet)
    plt.sci(nodeIm)
    plt.clim(110, 130)
    plt.colorbar()
    return voltChart
Пример #11
0
def _tests(Network, Equipment, keepFiles=True):
    import os, json, traceback, shutil
    from solvers import gridlabd
    from matplotlib import pyplot as plt
    import feeder
    exceptionCount = 0
    try:
        #db_network = os.path.abspath('./uploads/IEEE13.mdb')
        #db_equipment = os.path.abspath('./uploads/IEEE13.mdb')
        prefix = str(Path("testPEC.py").resolve()).strip(
            'scratch\cymeToGridlabTests\testPEC.py') + "\uploads\\"
        db_network = "C" + prefix + Network
        db_equipment = "C" + prefix + Equipment
        id_feeder = '650'
        conductors = prefix + "conductor_data.csv"
        #print "dbnet", db_network
        #print "eqnet", db_equipment
        #print "conductors", conductors
        #cyme_base, x, y = convertCymeModel(db_network, db_equipment, id_feeder, conductors)
        cyme_base, x, y = convertCymeModel(str(db_network),
                                           str(db_equipment),
                                           test=True,
                                           type=2,
                                           feeder_id='CV160')
        feeder.attachRecorders(cyme_base, "TriplexLosses", None, None)
        feeder.attachRecorders(cyme_base, "TransformerLosses", None, None)
        glmString = feeder.sortedWrite(cyme_base)
        feederglm = "C:\Users\Asus\Documents\GitHub\omf\omf\uploads\PEC.glm"
        #print "feeederglm", feederglm
        gfile = open(feederglm, 'w')
        gfile.write(glmString)
        gfile.close()
        #print 'WROTE GLM FOR'
        outPrefix = "C:\Users\Asus\Documents\GitHub\omf\omf\scratch\cymeToGridlabTests\\"
        try:
            os.mkdir(outPrefix)
        except:
            pass  # Directory already there.
        '''Attempt to graph'''
        try:
            # Draw the GLM.
            print "trying to graph"
            myGraph = feeder.treeToNxGraph(cyme_base)
            feeder.latLonNxGraph(myGraph, neatoLayout=False)
            plt.savefig(outPrefix + "PEC.png")
            print "outprefix", outPrefix + "PEC.png"
            print 'DREW GLM OF'
        except:
            exceptionCount += 1
            print 'FAILED DRAWING'
        try:
            # Run powerflow on the GLM.
            output = gridlabd.runInFilesystem(glmString, keepFiles=False)
            with open(outPrefix + "PEC.JSON", 'w') as outFile:
                json.dump(output, outFile, indent=4)
            print 'RAN GRIDLAB ON\n'
        except:
            exceptionCount += 1
            print 'POWERFLOW FAILED'
    except:
        print 'FAILED CONVERTING'
        exceptionCount += 1
        traceback.print_exc()
    if not keepFiles:
        shutil.rmtree(outPrefix)
    return exceptionCount
    '''db_network = os.path.abspath('./uploads/PasoRobles11cymsectiondevice[device]['phases']08.mdb')
def generateVoltChart(tree, rawOut, modelDir, neatoLayout=True):
	''' Map the voltages on a feeder over time using a movie.'''
	# We need to timestamp frames with the system clock to make sure the browser caches them appropriately.
	genTime = str(datetime.datetime.now()).replace(':','.')
	# Detect the feeder nominal voltage:
	for key in tree:
		ob = tree[key]
		if type(ob)==dict and ob.get('bustype','')=='SWING':
			feedVoltage = float(ob.get('nominal_voltage',1))
	# Make a graph object.
	fGraph = feeder.treeToNxGraph(tree)
	if neatoLayout:
		# HACK: work on a new graph without attributes because graphViz tries to read attrs.
		cleanG = nx.Graph(fGraph.edges())
		cleanG.add_nodes_from(fGraph)
		positions = nx.graphviz_layout(cleanG, prog='neato')
	else:
		rawPositions = {n:fGraph.node[n].get('pos',(0,0)) for n in fGraph}
		#HACK: the import code reverses the y coords.
		def yFlip(pair):
			try: return (pair[0], -1.0*pair[1])
			except: return (0,0)
		positions = {k:yFlip(rawPositions[k]) for k in rawPositions}
	# Plot all time steps.
	nodeVolts = {}
	for step, stamp in enumerate(rawOut['aVoltDump.csv']['# timestamp']):
		# Build voltage map.
		nodeVolts[step] = {}
		for nodeName in [x for x in rawOut['aVoltDump.csv'].keys() if x != '# timestamp']:
			allVolts = []
			for phase in ['a','b','c']:
				voltStep = rawOut[phase + 'VoltDump.csv'][nodeName][step]
				# HACK: Gridlab complex number format sometimes uses i, sometimes j, sometimes d. WTF?
				if type(voltStep) is str: voltStep = voltStep.replace('i','j')
				v = complex(voltStep)
				phaseVolt = abs(v)
				if phaseVolt != 0.0:
					if _digits(phaseVolt)>3:
						# Normalize to 120 V standard
						phaseVolt = phaseVolt*(120/feedVoltage)
					allVolts.append(phaseVolt)
			# HACK: Take average of all phases to collapse dimensionality.
			nodeVolts[step][nodeName] = avg(allVolts)
	# Draw animation.
	voltChart = plt.figure(figsize=(10,10))
	plt.axes(frameon = 0)
	plt.axis('off')
	voltChart.subplots_adjust(left=0.03, bottom=0.03, right=0.97, top=0.97, wspace=None, hspace=None)
	custom_cm = matplotlib.colors.LinearSegmentedColormap.from_list('custColMap',[(0.0,'blue'),(0.25,'darkgray'),(0.75,'darkgray'),(1.0,'yellow')])
	edgeIm = nx.draw_networkx_edges(fGraph, positions)
	nodeIm = nx.draw_networkx_nodes(fGraph,
		pos = positions,
		node_color = [nodeVolts[0].get(n,0) for n in fGraph.nodes()],
		linewidths = 0,
		node_size = 30,
		cmap = custom_cm)
	plt.sci(nodeIm)
	plt.clim(110,130)
	plt.colorbar()
	plt.title(rawOut['aVoltDump.csv']['# timestamp'][0])
	def update(step):
		nodeColors = np.array([nodeVolts[step].get(n,0) for n in fGraph.nodes()])
		plt.title(rawOut['aVoltDump.csv']['# timestamp'][step])
		nodeIm.set_array(nodeColors)
		return nodeColors,
	anim = FuncAnimation(voltChart, update, frames=len(rawOut['aVoltDump.csv']['# timestamp']), interval=200, blit=False)
	anim.save(pJoin(modelDir,'voltageChart.mp4'), codec='h264', extra_args=['-pix_fmt', 'yuv420p'])
	# Reclaim memory by closing, deleting and garbage collecting the last chart.
	voltChart.clf()
	plt.close()
	del voltChart
	gc.collect()
	return genTime
Пример #13
0
def generateVoltChart(tree, rawOut, modelDir, neatoLayout=True):
	''' Map the voltages on a feeder over time using a set of PNGs.'''
	# Make the subfolder we need.
	try: shutil.rmtree(pJoin(modelDir, 'pngs'))
	except: pass
	try: os.mkdir(pJoin(modelDir, 'pngs'))
	except: pass
	# We need to timestamp images with the system clock to make sure the browser caches them appropriately.
	genTime = str(datetime.datetime.now()).replace(':','.')
	# Detect the feeder nominal voltage:
	for key in tree:
		ob = tree[key]
		if type(ob)==dict and ob.get('bustype','')=='SWING':
			feedVoltage = float(ob.get('nominal_voltage',1))
	# Make a graph object.
	fGraph = feeder.treeToNxGraph(tree)
	if neatoLayout:
		# HACK: work on a new graph without attributes because graphViz tries to read attrs.
		cleanG = nx.Graph(fGraph.edges())
		cleanG.add_nodes_from(fGraph)
		positions = nx.graphviz_layout(cleanG, prog='neato')
	else:
		rawPositions = {n:fGraph.node[n].get('pos',(0,0)) for n in fGraph}
		#HACK: the import code reverses the y coords.
		def yFlip(pair):
			try: return (pair[0], -1.0*pair[1])
			except: return (0,0)
		positions = {k:yFlip(rawPositions[k]) for k in rawPositions}
	# Plot all time steps.
	for step, stamp in enumerate(rawOut['aVoltDump.csv']['# timestamp']):
		# Build voltage map.
		nodeVolts = {}
		for nodeName in [x for x in rawOut['aVoltDump.csv'].keys() if x != '# timestamp']:
			allVolts = []
			for phase in ['a','b','c']:
				voltStep = rawOut[phase + 'VoltDump.csv'][nodeName][step]
				# HACK: Gridlab complex number format sometimes uses i, sometimes j, sometimes d. WTF?
				if type(voltStep) is str: voltStep = voltStep.replace('i','j')
				v = complex(voltStep)
				phaseVolt = abs(v)
				if phaseVolt != 0.0:
					if _digits(phaseVolt)>3:
						# Normalize to 120 V standard
						phaseVolt = phaseVolt*(120/feedVoltage)
					allVolts.append(phaseVolt)
			# HACK: Take average of all phases to collapse dimensionality.
			nodeVolts[nodeName] = avg(allVolts)
		# Apply voltage map and chart it.
		voltChart = plt.figure(figsize=(10,10))
		plt.axes(frameon = 0)
		plt.axis('off')
		custom_cm = matplotlib.colors.LinearSegmentedColormap.from_list('custColMap',[(0.0,'blue'),(0.25,'darkgray'),(0.75,'darkgray'),(1.0,'yellow')])
		edgeIm = nx.draw_networkx_edges(fGraph, positions)
		nodeIm = nx.draw_networkx_nodes(fGraph,
			pos = positions,
			node_color = [nodeVolts.get(n,0) for n in fGraph.nodes()],
			linewidths = 0,
			node_size = 30,
			cmap = custom_cm)
		plt.sci(nodeIm)
		plt.clim(110,130)
		plt.colorbar()
		plt.title(stamp)
		voltChart.savefig(pJoin(modelDir,'pngs','volts' + str(step).zfill(3) + "-" + genTime + '.png'))
		# Reclaim memory by closing, deleting and garbage collecting the last chart.
		voltChart.clf()
		plt.close()
		del voltChart
		gc.collect()
	return genTime