コード例 #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
ファイル: 0milToGridlabTests.py プロジェクト: cdkkim/omf
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
ファイル: cvrStatic.py プロジェクト: mannanj/omf
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 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')
コード例 #7
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')
コード例 #8
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')