Example #1
0
	def runPowerflowIter(tree,scadaSubPower, iterationTimes):
		'''Runs powerflow once, then iterates.'''
		print "Running calibration powerflow #1."
		output = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=gridlabdDir)
		outRealPow = output["caliSub.csv"]["measured_real_power"]
		outImagPower = output["caliSub.csv"]["measured_reactive_power"]
		outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5/1000 for x in zip(outRealPow, outImagPower)]
		lastFile = "subScada.player"
		nextFile = "subScadaCalibrated.player"
		nextPower = outAppPowerKw
		for i in range(1, iterationTimes+1):
			SCAL_CONST = sum(scadaSubPower[1:simLength])/sum(nextPower[1:simLength])
			print "Running calibration powerflow (iteration", str(i+1), "of", iterationTimes+1,") (SCAL_CONST: ", SCAL_CONST,")"
			newPlayData = []
			with open(pJoin(gridlabdDir, lastFile), "r") as playerFile:
				for line in playerFile:
					(key,val) = line.split(',')
					newPlayData.append(str(key) + ',' + str(float(val)*SCAL_CONST) + "\n")
			with open(pJoin(gridlabdDir, nextFile), "w") as playerFile:
				for row in newPlayData:
					playerFile.write(row)
			tree[playerKey]["file"] = nextFile
			tree[outputRecorderKey]["file"] = "caliSubCheck.csv"
			nextOutput = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=gridlabdDir)
			outRealPow2nd = nextOutput["caliSubCheck.csv"]["measured_real_power"]
			outImagPower2nd = nextOutput["caliSubCheck.csv"]["measured_reactive_power"]
			nextAppKw = [(x[0]**2 + x[1]**2)**0.5/1000
				for x in zip(outRealPow2nd, outImagPower2nd)]
			lastFile = nextFile
			nextFile = "subScadaCalibrated"+str(i)+".player"
			nextPower = outAppPowerKw
		return outRealPow, outRealPow2nd, lastFile
Example #2
0
 def runPowerflowIter(tree, scadaSubPower):
     '''Runs powerflow once, then iterates.'''
     # Run initial powerflow to get power.
     print "Running initial calibration powerflow."
     output = gridlabd.runInFilesystem(tree,
                                       keepFiles=True,
                                       workDir=gridlabdDir)
     outRealPow = output["caliSub.csv"]["measured_real_power"]
     outImagPower = output["caliSub.csv"]["measured_reactive_power"]
     outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5 / 1000
                      for x in zip(outRealPow, outImagPower)]
     lastFile = "subScada.player"
     nextFile = "subScadaCalibrated.player"
     nextPower = outAppPowerKw
     error = (sum(outRealPow[1:simLength]) / 1000 - sum(
         scadaSubPower[1:simLength])) / sum(scadaSubPower[1:simLength])
     iteration = 1
     while abs(error) > calibrateError and iteration < 5:
         # Run calibration and iterate up to 5 times.
         SCAL_CONST = sum(scadaSubPower[1:simLength]) / sum(
             nextPower[1:simLength])
         print "Calibrating loads, running powerflow again. Our SCAL_CONST is: ", SCAL_CONST
         newPlayData = []
         with open(pJoin(gridlabdDir, lastFile), "r") as playerFile:
             for line in playerFile:
                 (key, val) = line.split(',')
                 newPlayData.append(
                     str(key) + ',' + str(float(val) * SCAL_CONST) + "\n")
         with open(pJoin(gridlabdDir, nextFile), "w") as playerFile:
             for row in newPlayData:
                 playerFile.write(row)
         tree[playerKey]["file"] = nextFile
         tree[outputRecorderKey]["file"] = "caliSubCheck.csv"
         nextOutput = gridlabd.runInFilesystem(tree,
                                               keepFiles=True,
                                               workDir=gridlabdDir)
         outRealPowIter = nextOutput["caliSubCheck.csv"][
             "measured_real_power"]
         outImagPowerIter = nextOutput["caliSubCheck.csv"][
             "measured_reactive_power"]
         nextAppKw = [(x[0]**2 + x[1]**2)**0.5 / 1000
                      for x in zip(outRealPowIter, outImagPowerIter)]
         lastFile = nextFile
         nextFile = "subScadaCalibrated" + str(iteration) + ".player"
         nextPower = nextAppKw
         # Compute error and iterate.
         error = (sum(outRealPowIter[1:simLength]) / 1000 - sum(
             scadaSubPower[1:simLength])) / sum(scadaSubPower[1:simLength])
         iteration += 1
         print "Error:", abs(error * 100), "% Iteration:", iteration
     return outRealPow, outRealPowIter, lastFile, iteration
Example #3
0
def runBeckGridlab():
	try:
		os.remove('./beckDebuggery')
	except:
		pass
	os.mkdir('./beckDebuggery')
	rawOut = gridlabd.runInFilesystem(tree,
			attachments=myFeeder.get('attachments',{}), keepFiles=True,
			workDir='./beckDebuggery', glmName=None)
Example #4
0
	def runPowerflowIter(tree,scadaSubPower):
		'''Runs powerflow once, then iterates.'''
		# Run initial powerflow to get power.
		print "Starting calibration."
		print "Goal of calibration: Error: %s, Iterations: <%s, trim: %s"%(calibrateError[0], calibrateError[1], trim)		
		output = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=pJoin(workDir,"gridlabD"))
		outRealPow = output["caliSub.csv"]["measured_real_power"][trim:simLength]
		outImagPower = output["caliSub.csv"]["measured_reactive_power"][trim:simLength]
		outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5/1000 for x in zip(outRealPow, outImagPower)]
		lastFile = "subScada.player"
		nextFile = "subScadaCalibrated.player"
		nextPower = outAppPowerKw
		error = (sum(outRealPow)/1000-sum(scadaSubPower))/sum(scadaSubPower)
		iteration = 1
		print "First error:", error
		while abs(error)>calibrateError[0] and iteration<calibrateError[1]:
			# Run calibration and iterate up to 5 times.
			SCAL_CONST = sum(scadaSubPower)/sum(nextPower)
			print "Calibrating & running again... Error: %s, Iteration: %s, SCAL_CONST: %s"%(str(round(abs(error*100),2)), str(iteration), round(SCAL_CONST,2))
			newPlayData = []
			with open(pJoin(pJoin(workDir,"gridlabD"), lastFile), "r") as playerFile:
				for line in playerFile:
					(key,val) = line.split(',')
					newPlayData.append(str(key) + ',' + str(float(val)*SCAL_CONST) + "\n")
			with open(pJoin(pJoin(workDir,"gridlabD"), nextFile), "w") as playerFile:
				for row in newPlayData:
					playerFile.write(row)
			tree[playerKey]["file"] = nextFile
			tree[outputRecorderKey]["file"] = "caliSubCheck.csv"
			nextOutput = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=pJoin(workDir,"gridlabD"))
			outRealPowIter = nextOutput["caliSubCheck.csv"]["measured_real_power"][trim:simLength]
			outImagPowerIter = nextOutput["caliSubCheck.csv"]["measured_reactive_power"][trim:simLength]
			nextAppKw = [(x[0]**2 + x[1]**2)**0.5/1000
				for x in zip(outRealPowIter, outImagPowerIter)]
			lastFile = nextFile
			nextFile = "subScadaCalibrated"+str(iteration)+".player"
			nextPower = nextAppKw
			# Compute error and iterate.
			error = (sum(outRealPowIter)/1000-sum(scadaSubPower))/sum(scadaSubPower)
			iteration+=1
		else:
			if iteration==1: outRealPowIter = outRealPow
		print "Calibration done: Error: %s, Iteration: %s, SCAL_CONST: %s"%(str(round(abs(error*100),2)), str(iteration), round(SCAL_CONST,2))		
		return outRealPow, outRealPowIter, lastFile, iteration
Example #5
0
def runBeckGridlab():
    try:
        os.remove('./beckDebuggery')
    except:
        pass
    os.mkdir('./beckDebuggery')
    rawOut = gridlabd.runInFilesystem(tree,
                                      attachments=myFeeder.get(
                                          'attachments', {}),
                                      keepFiles=True,
                                      workDir='./beckDebuggery',
                                      glmName=None)
	def runPowerflowIter(tree,scadaSubPower):
		'''Runs powerflow once, then iterates.'''
		# Run initial powerflow to get power.
		print "Running initial calibration powerflow."
		output = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=gridlabdDir)
		outRealPow = output["caliSub.csv"]["measured_real_power"]
		outImagPower = output["caliSub.csv"]["measured_reactive_power"]
		outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5/1000 for x in zip(outRealPow, outImagPower)]
		lastFile = "subScada.player"
		nextFile = "subScadaCalibrated.player"
		nextPower = outAppPowerKw
		error = (sum(outRealPow[1:simLength])/1000-sum(scadaSubPower[1:simLength]))/sum(scadaSubPower[1:simLength])
		iteration = 1
		while abs(error)>calibrateError and iteration<5:
			# Run calibration and iterate up to 5 times.
			SCAL_CONST = sum(scadaSubPower[1:simLength])/sum(nextPower[1:simLength])
			print "Calibrating loads, running powerflow again. Our SCAL_CONST is: ", SCAL_CONST
			newPlayData = []
			with open(pJoin(gridlabdDir, lastFile), "r") as playerFile:
				for line in playerFile:
					(key,val) = line.split(',')
					newPlayData.append(str(key) + ',' + str(float(val)*SCAL_CONST) + "\n")
			with open(pJoin(gridlabdDir, nextFile), "w") as playerFile:
				for row in newPlayData:
					playerFile.write(row)
			tree[playerKey]["file"] = nextFile
			tree[outputRecorderKey]["file"] = "caliSubCheck.csv"
			nextOutput = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=gridlabdDir)
			outRealPowIter = nextOutput["caliSubCheck.csv"]["measured_real_power"]
			outImagPowerIter = nextOutput["caliSubCheck.csv"]["measured_reactive_power"]
			nextAppKw = [(x[0]**2 + x[1]**2)**0.5/1000
				for x in zip(outRealPowIter, outImagPowerIter)]
			lastFile = nextFile
			nextFile = "subScadaCalibrated"+str(iteration)+".player"
			nextPower = nextAppKw
			# Compute error and iterate.
			error = (sum(outRealPowIter[1:simLength])/1000-sum(scadaSubPower[1:simLength]))/sum(scadaSubPower[1:simLength])
			iteration+=1
			print "Error:", abs(error*100), "% Iteration:", iteration
		return outRealPow, outRealPowIter, lastFile, iteration
Example #7
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
Example #8
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
Example #9
0
def runForeground(modelDir, inputDict):
	''' Run the model in its directory. WARNING: GRIDLAB CAN TAKE HOURS TO COMPLETE. '''
	# Check whether model exist or not
	if not os.path.isdir(modelDir):
		os.makedirs(modelDir)
		inputDict["created"] = str(datetime.datetime.now())	
	print "STARTING TO RUN", modelDir
	beginTime = datetime.datetime.now()
	feederList = []
	# Get prepare of data and clean workspace if re-run, If re-run remove all the data in the subfolders
	for dirs in os.listdir(modelDir):
		if os.path.isdir(pJoin(modelDir, dirs)):
			shutil.rmtree(pJoin(modelDir, dirs))
	# Get each feeder, prepare data in separate folders, and run there.
	for key in sorted(inputDict, key=inputDict.get):
		if key.startswith("feederName"):
			feederDir, feederName = inputDict[key].split("___")
			feederList.append(feederName)
			try:
				os.remove(pJoin(modelDir, feederName, "allOutputData.json"))
			except Exception, e:
				pass
			if not os.path.isdir(pJoin(modelDir, feederName)):
				os.makedirs(pJoin(modelDir, feederName)) # create subfolders for feeders
			shutil.copy(pJoin(__metaModel__._omfDir, "data", "Feeder", feederDir, feederName + ".json"),
				pJoin(modelDir, feederName, "feeder.json"))
			inputDict["climateName"], latforpvwatts = zipCodeToClimateName(inputDict["zipCode"])			
			shutil.copy(pJoin(__metaModel__._omfDir, "data", "Climate", inputDict["climateName"] + ".tmy2"),
				pJoin(modelDir, feederName, "climate.tmy2"))
			try:
				startTime = datetime.datetime.now()
				feederJson = json.load(open(pJoin(modelDir, feederName, "feeder.json")))
				tree = feederJson["tree"]
				# Set up GLM with correct time and recorders:
				feeder.attachRecorders(tree, "Regulator", "object", "regulator")
				feeder.attachRecorders(tree, "Capacitor", "object", "capacitor")
				feeder.attachRecorders(tree, "Inverter", "object", "inverter")
				feeder.attachRecorders(tree, "Windmill", "object", "windturb_dg")
				feeder.attachRecorders(tree, "CollectorVoltage", None, None)
				feeder.attachRecorders(tree, "Climate", "object", "climate")
				feeder.attachRecorders(tree, "OverheadLosses", None, None)
				feeder.attachRecorders(tree, "UndergroundLosses", None, None)
				feeder.attachRecorders(tree, "TriplexLosses", None, None)
				feeder.attachRecorders(tree, "TransformerLosses", None, None)
				feeder.groupSwingKids(tree)
				feeder.adjustTime(tree=tree, simLength=float(inputDict["simLength"]),
					simLengthUnits=inputDict["simLengthUnits"], simStartDate=inputDict["simStartDate"])
				# RUN GRIDLABD IN FILESYSTEM (EXPENSIVE!)
				rawOut = gridlabd.runInFilesystem(tree, attachments=feederJson["attachments"], 
					keepFiles=True, workDir=pJoin(modelDir, feederName))
				cleanOut = {}
				# Std Err and Std Out
				cleanOut['stderr'] = rawOut['stderr']
				cleanOut['stdout'] = rawOut['stdout']
				# Time Stamps
				for key in rawOut:
					if '# timestamp' in rawOut[key]:
						cleanOut['timeStamps'] = rawOut[key]['# timestamp']
						break
					elif '# property.. timestamp' in rawOut[key]:
						cleanOut['timeStamps'] = rawOut[key]['# property.. timestamp']
					else:
						cleanOut['timeStamps'] = []
				# Day/Month Aggregation Setup:
				stamps = cleanOut.get('timeStamps',[])
				level = inputDict.get('simLengthUnits','hours')
				# Climate
				for key in rawOut:
					if key.startswith('Climate_') and key.endswith('.csv'):
						cleanOut['climate'] = {}
						cleanOut['climate']['Rain Fall (in/h)'] = hdmAgg(rawOut[key].get('rainfall'), sum, level)
						cleanOut['climate']['Wind Speed (m/s)'] = hdmAgg(rawOut[key].get('wind_speed'), avg, level)
						cleanOut['climate']['Temperature (F)'] = hdmAgg(rawOut[key].get('temperature'), max, level)
						cleanOut['climate']['Snow Depth (in)'] = hdmAgg(rawOut[key].get('snowdepth'), max, level)
						cleanOut['climate']['Direct Insolation (W/m^2)'] = hdmAgg(rawOut[key].get('solar_direct'), sum, level)
				# Voltage Band
				if 'VoltageJiggle.csv' in rawOut:
					cleanOut['allMeterVoltages'] = {}
					cleanOut['allMeterVoltages']['Min'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['min(voltage_12.mag)']], min, level)
					cleanOut['allMeterVoltages']['Mean'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['mean(voltage_12.mag)']], avg, level)
					cleanOut['allMeterVoltages']['StdDev'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['std(voltage_12.mag)']], avg, level)
					cleanOut['allMeterVoltages']['Max'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['max(voltage_12.mag)']], max, level)
				cleanOut['allMeterVoltages']['stdDevPos'] = [(x+y/2) for x,y in zip(cleanOut['allMeterVoltages']['Mean'], cleanOut['allMeterVoltages']['StdDev'])]
				cleanOut['allMeterVoltages']['stdDevNeg'] = [(x-y/2) for x,y in zip(cleanOut['allMeterVoltages']['Mean'], cleanOut['allMeterVoltages']['StdDev'])]
				# Total # of meters
				count = 0
				with open(pJoin(modelDir, feederName, "feeder.json")) as f:
					for line in f:
						if "\"objectType\": \"triplex_meter\"" in line:
							count+=1
				print "count=", count
				cleanOut['allMeterVoltages']['triplexMeterCount'] = float(count)
				# Power Consumption
				cleanOut['Consumption'] = {}
				# Set default value to be 0, avoiding missing value when computing Loads
				cleanOut['Consumption']['Power'] = [0] * int(inputDict["simLength"])
				cleanOut['Consumption']['Losses'] = [0] * int(inputDict["simLength"])
				cleanOut['Consumption']['DG'] = [0] * int(inputDict["simLength"])
				for key in rawOut:
					if key.startswith('SwingKids_') and key.endswith('.csv'):
						oneSwingPower = hdmAgg(vecPyth(rawOut[key]['sum(power_in.real)'],rawOut[key]['sum(power_in.imag)']), avg, level)
						if 'Power' not in cleanOut['Consumption']:
							cleanOut['Consumption']['Power'] = oneSwingPower
						else:
							cleanOut['Consumption']['Power'] = vecSum(oneSwingPower,cleanOut['Consumption']['Power'])
					elif key.startswith('Inverter_') and key.endswith('.csv'):
						realA = rawOut[key]['power_A.real']
						realB = rawOut[key]['power_B.real']
						realC = rawOut[key]['power_C.real']
						imagA = rawOut[key]['power_A.imag']
						imagB = rawOut[key]['power_B.imag']
						imagC = rawOut[key]['power_C.imag']
						oneDgPower = hdmAgg(vecSum(vecPyth(realA,imagA),vecPyth(realB,imagB),vecPyth(realC,imagC)), avg, level)
						if 'DG' not in cleanOut['Consumption']:
							cleanOut['Consumption']['DG'] = oneDgPower
						else:
							cleanOut['Consumption']['DG'] = vecSum(oneDgPower,cleanOut['Consumption']['DG'])
					elif key.startswith('Windmill_') and key.endswith('.csv'):
						vrA = rawOut[key]['voltage_A.real']
						vrB = rawOut[key]['voltage_B.real']
						vrC = rawOut[key]['voltage_C.real']
						viA = rawOut[key]['voltage_A.imag']
						viB = rawOut[key]['voltage_B.imag']
						viC = rawOut[key]['voltage_C.imag']
						crB = rawOut[key]['current_B.real']
						crA = rawOut[key]['current_A.real']
						crC = rawOut[key]['current_C.real']
						ciA = rawOut[key]['current_A.imag']
						ciB = rawOut[key]['current_B.imag']
						ciC = rawOut[key]['current_C.imag']
						powerA = vecProd(vecPyth(vrA,viA),vecPyth(crA,ciA))
						powerB = vecProd(vecPyth(vrB,viB),vecPyth(crB,ciB))
						powerC = vecProd(vecPyth(vrC,viC),vecPyth(crC,ciC))
						# HACK: multiply by negative one because turbine power sign is opposite all other DG:
						oneDgPower = [-1.0 * x for x in hdmAgg(vecSum(powerA,powerB,powerC), avg, level)]
						if 'DG' not in cleanOut['Consumption']:
							cleanOut['Consumption']['DG'] = oneDgPower
						else:
							cleanOut['Consumption']['DG'] = vecSum(oneDgPower,cleanOut['Consumption']['DG'])
					elif key in ['OverheadLosses.csv', 'UndergroundLosses.csv', 'TriplexLosses.csv', 'TransformerLosses.csv']:
						realA = rawOut[key]['sum(power_losses_A.real)']
						imagA = rawOut[key]['sum(power_losses_A.imag)']
						realB = rawOut[key]['sum(power_losses_B.real)']
						imagB = rawOut[key]['sum(power_losses_B.imag)']
						realC = rawOut[key]['sum(power_losses_C.real)']
						imagC = rawOut[key]['sum(power_losses_C.imag)']
						oneLoss = hdmAgg(vecSum(vecPyth(realA,imagA),vecPyth(realB,imagB),vecPyth(realC,imagC)), avg, level)
						if 'Losses' not in cleanOut['Consumption']:
							cleanOut['Consumption']['Losses'] = oneLoss
						else:
							cleanOut['Consumption']['Losses'] = vecSum(oneLoss,cleanOut['Consumption']['Losses'])
				# Aggregate up the timestamps:
				if level=='days':
					cleanOut['timeStamps'] = aggSeries(stamps, stamps, lambda x:x[0][0:10], 'days')
				elif level=='months':
					cleanOut['timeStamps'] = aggSeries(stamps, stamps, lambda x:x[0][0:7], 'months')
				# Write the output.
				with open(pJoin(modelDir, feederName, "allOutputData.json"),"w") as outFile:
					json.dump(cleanOut, outFile, indent=4)
				# 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, feederName, "allInputData.json"),"w") as inFile:
					json.dump(inputDict, inFile, indent=4)
				# Clean up the PID file.
				os.remove(pJoin(modelDir, feederName,"PID.txt"))
				print "DONE RUNNING GRIDLABMULTI", modelDir, feederName
			except Exception as e:
				print "MODEL CRASHED GRIDLABMULTI", e, modelDir, feederName
				cancel(pJoin(modelDir, feederName))
				with open(pJoin(modelDir, feederName, "stderr.txt"), "a+") as stderrFile:
					traceback.print_exc(file = stderrFile)
Example #10
0
def attachVolts(workDir, feederPath, voltVectorA, voltVectorB, voltVectorC,
                simStartDate, simLength, simLengthUnits):
    '''read voltage vectors of 3 different phases, run gridlabd, and attach output to the feeder.'''
    try:
        timeStamp = [simStartDate['Date']]
        for x in range(1, 8760):
            timeStamp.append(timeStamp[x - 1] + dt.timedelta(hours=1))
        firstDateTime = timeStamp[1]
        with open(pJoin(pJoin(workDir, "gridlabD"), "phaseAVoltage.player"),
                  "w") as voltFile:
            for x in range(0, 8760):
                timestamp = timeStamp[x]
                voltage = str("%0.2f" % float(voltVectorA[x])) + "+0j"
                line = timestamp.strftime(
                    "%Y-%m-%d %H:%M:%S"
                ) + " " + simStartDate['timeZone'] + "," + str(voltage) + "\n"
                voltFile.write(line)
        with open(pJoin(pJoin(workDir, "gridlabD"), "phaseBVoltage.player"),
                  "w") as voltFile:
            for x in range(0, 8760):
                timestamp = timeStamp[x]
                voltage = str("%0.2f" % float(voltVectorB[x])) + "-" + str(
                    "%0.4f" % float(random.uniform(6449, 6460))) + "j"
                line = timestamp.strftime(
                    "%Y-%m-%d %H:%M:%S"
                ) + " " + simStartDate['timeZone'] + "," + str(voltage) + "\n"
                voltFile.write(line)
        with open(pJoin(pJoin(workDir, "gridlabD"), "phaseCVoltage.player"),
                  "w") as voltFile:
            for x in range(0, 8760):
                timestamp = timeStamp[x]
                voltage = str("%0.2f" % float(voltVectorC[x])) + "+" + str(
                    "%0.4f" % float(random.uniform(6449, 6460))) + "j"
                line = timestamp.strftime(
                    "%Y-%m-%d %H:%M:%S"
                ) + " " + simStartDate['timeZone'] + "," + str(voltage) + "\n"
                voltFile.write(line)
        with open(feederPath, "r") as jsonIn:
            feederJson = json.load(jsonIn)
            tree = feederJson.get("tree", {})
        # Find swingNode name.
        for key in tree:
            if tree[key].get('bustype', '').lower() == 'swing':
                swingName = tree[key].get('name')
        # Attach player.
        classOb = {'omftype': 'class player', 'argument': '{double value;}'}
        voltageObA = {
            "object": "player",
            "property": "voltage_A",
            "file": "phaseAVoltage.player",
            "loop": "0",
            "parent": swingName
        }
        voltageObB = {
            "object": "player",
            "property": "voltage_B",
            "file": "phaseBVoltage.player",
            "loop": "0",
            "parent": swingName
        }
        voltageObC = {
            "object": "player",
            "property": "voltage_C",
            "file": "phaseCVoltage.player",
            "loop": "0",
            "parent": swingName
        }
        maxKey = feeder.getMaxKey(tree)
        voltplayerKeyA = maxKey + 2
        voltplayerKeyB = maxKey + 3
        voltplayerKeyC = maxKey + 4
        tree[maxKey + 1] = classOb
        tree[voltplayerKeyA] = voltageObA
        tree[voltplayerKeyB] = voltageObB
        tree[voltplayerKeyC] = voltageObC
        # Adjust time and run output.
        feeder.adjustTime(tree, simLength, simLengthUnits,
                          firstDateTime.strftime("%Y-%m-%d %H:%M:%S"))
        output = gridlabd.runInFilesystem(tree,
                                          keepFiles=True,
                                          workDir=pJoin(workDir, "gridlabD"))
        # Write the output.
        with open(pJoin(workDir, "calibratedFeeder.omd"), "w") as outJson:
            playerStringA = open(
                pJoin(pJoin(workDir, "gridlabD"),
                      "phaseAVoltage.player")).read()
            playerStringB = open(
                pJoin(pJoin(workDir, "gridlabD"),
                      "phaseBVoltage.player")).read()
            playerStringC = open(
                pJoin(pJoin(workDir, "gridlabD"),
                      "phaseCVoltage.player")).read()
            feederJson["attachments"]["phaseAVoltage.player"] = playerStringA
            feederJson["attachments"]["phaseBVoltage.player"] = playerStringB
            feederJson["attachments"]["phaseCVoltage.player"] = playerStringC
            feederJson["tree"] = tree
            json.dump(feederJson, outJson, indent=4)
        return pJoin(workDir, "calibratedFeeder.omd"), True
    except:
        print "Failed to run gridlabD with voltage players."
        return "", False
Example #11
0
def runForeground(modelDir, inData):
    '''This reads a glm file, changes the method of powerflow and reruns'''
    print "STARTING TO RUN", modelDir
    try:
        startTime = datetime.now()
        if not os.path.isdir(modelDir):
            os.makedirs(modelDir)
            inData["created"] = str(startTime)
        #read pre-calibrated feeder and run cvrdynamic
        feederName = inData.get('feederName1', 'feeder1')
        feederPath = pJoin(modelDir, feederName + '.omd')
        # Reads a pre-calibrated feeder.
        allOutput = {}
        with open(feederPath, "r") as jsonIn:
            feederJson = json.load(jsonIn)
            localTree = feederJson.get("tree", {})
            attachments = feederJson.get("attachments", {})
        for key in localTree:
            if "solver_method" in localTree[key].keys():
                # print "current solver method", localTree[key]["solver_method"]
                localTree[key]["solver_method"] = 'FBS'
        #find the swing bus and recorder attached to substation
        try:
            for key in localTree:
                if localTree[key].get('bustype', '').lower() == 'swing':
                    swingIndex = key
                    swingName = localTree[key].get('name')
                if localTree[key].get(
                        'object', '') == 'regulator' and localTree[key].get(
                            'from', '') == swingName:
                    regIndex = key
                    regConfName = localTree[key]['configuration']
        except:
            raise ValueError('Invalid feeder selected:',
                             str(inData["feederName1"]))
        #find the regulator and capacitor names and combine to form a string for volt-var control object
        regKeys = []
        accum_reg = ""
        for key in localTree:
            if localTree[key].get("object", "") == "regulator":
                accum_reg += localTree[key].get("name", "ERROR") + ","
                regKeys.append(key)
        regstr = accum_reg[:-1]
        # print regKeys
        capKeys = []
        accum_cap = ""
        for key in localTree:
            if localTree[key].get("object", "") == "capacitor":
                accum_cap += localTree[key].get("name", "ERROR") + ","
                capKeys.append(key)
                if localTree[key].get("control", "").lower() == "manual":
                    localTree[key]['control'] = "VOLT"
                    # print "changing capacitor control from manual to volt"
        capstr = accum_cap[:-1]
        # print capKeys
        # 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':
            localTree[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': localTree[swingIndex]['name'],
            'property': 'voltage_A,voltage_B,voltage_C'
        }, {
            'object': 'recorder',
            'file': 'ZsubstationBottom.csv',
            'limit': '0',
            'parent': localTree[regIndex]['to'],
            'property': 'voltage_A,voltage_B,voltage_C'
        }]
        #recorder object for capacitor switching - if capacitors exist
        if capKeys != []:
            for key in capKeys:
                recorders.append({
                    'object': 'recorder',
                    'file': 'ZcapSwitch' + str(key) + '.csv',
                    'limit': '0',
                    'parent': localTree[key]['name'],
                    'property': 'switchA,switchB,switchC'
                })
        #attach recorder process
        biggest = 1 + max([int(k) for k in localTree.keys()])
        for index, rec in enumerate(recorders):
            localTree[biggest + index] = rec
        #run a reference load flow
        HOURS = float(inData['simLengthHours'])
        simStartDate = inData['simStart']
        feeder.adjustTime(localTree, HOURS, "hours", simStartDate)
        output = gridlabd.runInFilesystem(localTree,
                                          attachments,
                                          keepFiles=False,
                                          workDir=modelDir)
        try:
            os.remove(pJoin(modelDir, "PID.txt"))
        except:
            pass
        p = output['Zregulator.csv']['power_in.real']
        q = output['Zregulator.csv']['power_in.imag']
        #calculating length of simulation because it migth be different from the simulation input HOURS
        simRealLength = int(len(p))
        #time delays from configuration files
        time_delay_reg = '30.0'
        time_delay_cap = '300.0'
        for key in localTree:
            if localTree[key].get('object', '') == "regulator_configuration":
                time_delay_reg = localTree[key]['time_delay']
                # print "time_delay_reg",time_delay_reg
            # if localTree[key].get('object','') == "capacitor":
            # 	time_delay_cap = localTree[key]['time_delay']
            # 	print "time_delay_cap",time_delay_cap
        #change the recorder names
        for key in localTree:
            if localTree[key].get('object',
                                  '') == "collector" or localTree[key].get(
                                      'object', '') == "recorder":
                if localTree[key].get('file', '').startswith('Z'):
                    localTree[key]['file'] = localTree[key].get(
                        'file', '').replace('Z', 'NewZ')
        #create volt-var control object
        max_key = max([int(key) for key in localTree.keys()])
        # print max_key
        localTree[max_key + 1] = {
            'object': 'volt_var_control',
            'name': 'IVVC1',
            'control_method': 'ACTIVE',
            'capacitor_delay': str(time_delay_cap),
            'regulator_delay': str(time_delay_reg),
            'desired_pf': '0.99',
            'd_max': '0.6',
            'd_min': '0.1',
            'substation_link': str(localTree[regIndex]['name']),
            'regulator_list': regstr,
            'capacitor_list': capstr,
            'voltage_measurements': str(inData.get("voltageNodes", 0)),
        }
        #running powerflow analysis via gridalab after attaching a regulator
        feeder.adjustTime(localTree, HOURS, "hours", simStartDate)
        output1 = gridlabd.runInFilesystem(localTree,
                                           attachments,
                                           keepFiles=True,
                                           workDir=modelDir)
        os.remove(pJoin(modelDir, "PID.txt"))
        pnew = output1['NewZregulator.csv']['power_in.real']
        qnew = output1['NewZregulator.csv']['power_in.imag']

        #total real and imaginary losses as a function of time
        def vecSum(u, v):
            ''' Add vectors u and v element-wise. Return has len <= len(u) and <=len(v). '''
            return map(sum, zip(u, v))

        def zeroVec(length):
            ''' Give a zero vector of input length. '''
            return [0 for x in xrange(length)]

        (realLoss, imagLoss, realLossnew, imagLossnew) = (zeroVec(int(HOURS))
                                                          for x in range(4))
        for device in [
                'ZlossesOverhead.csv', 'ZlossesTransformer.csv',
                'ZlossesUnderground.csv'
        ]:
            for letter in ['A', 'B', 'C']:
                realLoss = vecSum(
                    realLoss,
                    output[device]['sum(power_losses_' + letter + '.real)'])
                imagLoss = vecSum(
                    imagLoss,
                    output[device]['sum(power_losses_' + letter + '.imag)'])
                realLossnew = vecSum(
                    realLossnew, output1['New' + device]['sum(power_losses_' +
                                                         letter + '.real)'])
                imagLossnew = vecSum(
                    imagLossnew, output1['New' + device]['sum(power_losses_' +
                                                         letter + '.imag)'])
        #voltage calculations and tap calculations
        def divby2(u):
            '''divides by 2'''
            return u / 2

        lowVoltage = []
        meanVoltage = []
        highVoltage = []
        lowVoltagenew = []
        meanVoltagenew = []
        highVoltagenew = []
        tap = {'A': [], 'B': [], 'C': []}
        tapnew = {'A': [], 'B': [], 'C': []}
        volt = {'A': [], 'B': [], 'C': []}
        voltnew = {'A': [], 'B': [], 'C': []}
        switch = {'A': [], 'B': [], 'C': []}
        switchnew = {'A': [], 'B': [], 'C': []}
        for letter in ['A', 'B', 'C']:
            tap[letter] = output['Zregulator.csv']['tap_' + letter]
            tapnew[letter] = output1['NewZregulator.csv']['tap_' + letter]
            if capKeys != []:
                switch[letter] = output['ZcapSwitch' + str(int(capKeys[0])) +
                                        '.csv']['switch' + letter]
                switchnew[letter] = output1['NewZcapSwitch' +
                                            str(int(capKeys[0])) +
                                            '.csv']['switch' + letter]
            volt[letter] = map(
                returnMag,
                output['ZsubstationBottom.csv']['voltage_' + letter])
            voltnew[letter] = map(
                returnMag,
                output1['NewZsubstationBottom.csv']['voltage_' + letter])
        lowVoltage = map(divby2,
                         output['ZvoltageJiggle.csv']['min(voltage_12.mag)'])
        lowVoltagenew = map(
            divby2, output1['NewZvoltageJiggle.csv']['min(voltage_12.mag)'])
        meanVoltage = map(divby2,
                          output['ZvoltageJiggle.csv']['mean(voltage_12.mag)'])
        meanVoltagenew = map(
            divby2, output1['NewZvoltageJiggle.csv']['mean(voltage_12.mag)'])
        highVoltage = map(divby2,
                          output['ZvoltageJiggle.csv']['max(voltage_12.mag)'])
        highVoltagenew = map(
            divby2, output1['NewZvoltageJiggle.csv']['max(voltage_12.mag)'])
        #energy calculations
        whEnergy = []
        whLosses = []
        whLoads = []
        whEnergy.append(sum(p) / 10**6)
        whLosses.append(sum(realLoss) / 10**6)
        whLoads.append((sum(p) - sum(realLoss)) / 10**6)
        whEnergy.append(sum(pnew) / 10**6)
        whLosses.append(sum(realLossnew) / 10**6)
        whLoads.append((sum(pnew) - sum(realLossnew)) / 10**6)
        indices = ['No IVVC', 'With IVVC']
        # energySalesRed = (whLoads[1]-whLoads[0])*(inData['wholesaleEnergyCostPerKwh'])*1000
        # lossSav = (whLosses[0]-whLosses[1])*inData['wholesaleEnergyCostPerKwh']*1000
        # print energySalesRed, lossSav
        #plots
        ticks = []
        plt.clf()
        plt.title("total energy")
        plt.ylabel("total load and losses (MWh)")
        for element in range(2):
            ticks.append(element)
            bar_loss = plt.bar(element, whLosses[element], 0.15, color='red')
            bar_load = plt.bar(element + 0.15,
                               whLoads[element],
                               0.15,
                               color='orange')
        plt.legend([bar_load[0], bar_loss[0]], ['total load', 'total losses'],
                   bbox_to_anchor=(0., 0.915, 1., .102),
                   loc=3,
                   ncol=2,
                   mode="expand",
                   borderaxespad=0.1)
        plt.xticks([t + 0.15 for t in ticks], indices)
        plt.savefig(pJoin(modelDir, "totalEnergy.png"))
        #real and imaginary power
        plt.figure("real power")
        plt.title("Real Power at substation")
        plt.ylabel("substation real power (MW)")
        pMW = [element / 10**6 for element in p]
        pMWn = [element / 10**6 for element in pnew]
        pw = plt.plot(pMW)
        npw = plt.plot(pMWn)
        plt.legend([pw[0], npw[0]], ['NO IVVC', 'WITH IVVC'],
                   bbox_to_anchor=(0., 0.915, 1., .102),
                   loc=3,
                   ncol=2,
                   mode="expand",
                   borderaxespad=0.1)
        plt.savefig(pJoin(modelDir, "realPower.png"))
        plt.figure("Reactive power")
        plt.title("Reactive Power at substation")
        plt.ylabel("substation reactive power (MVAR)")
        qMVAR = [element / 10**6 for element in q]
        qMVARn = [element / 10**6 for element in qnew]
        iw = plt.plot(qMVAR)
        niw = plt.plot(qMVARn)
        plt.legend([iw[0], niw[0]], ['NO IVVC', 'WITH IVVC'],
                   bbox_to_anchor=(0., 0.915, 1., .102),
                   loc=3,
                   ncol=2,
                   mode="expand",
                   borderaxespad=0.1)
        plt.savefig(pJoin(modelDir, "imaginaryPower.png"))
        #voltage plots
        plt.figure("voltages as a function of time")
        f, ax = plt.subplots(2, sharex=True)
        f.suptitle("Min and Max voltages on the feeder")
        lv = ax[0].plot(lowVoltage, color='cadetblue')
        mv = ax[0].plot(meanVoltage, color='blue')
        hv = ax[0].plot(highVoltage, color='cadetblue')
        ax[0].legend([lv[0], mv[0], hv[0]],
                     ['low voltage', 'mean voltage', 'high voltage'],
                     bbox_to_anchor=(0., 0.915, 1., .1),
                     loc=3,
                     ncol=3,
                     mode="expand",
                     borderaxespad=0.1)
        ax[0].set_ylabel('NO IVVC')
        nlv = ax[1].plot(lowVoltagenew, color='cadetblue')
        nmv = ax[1].plot(meanVoltagenew, color='blue')
        nhv = ax[1].plot(highVoltagenew, color='cadetblue')
        ax[1].set_ylabel('WITH IVVC')
        plt.savefig(pJoin(modelDir, "Voltages.png"))
        #tap positions
        plt.figure("TAP positions NO IVVC")
        f, ax = plt.subplots(6, sharex=True)
        f.set_size_inches(10, 12.0)
        #f.suptitle("Regulator Tap positions")
        ax[0].plot(tap['A'])
        ax[0].set_title("Regulator Tap positions NO IVVC")
        ax[0].set_ylabel("TAP A")
        ax[1].plot(tap['B'])
        ax[1].set_ylabel("TAP B")
        ax[2].plot(tap['C'])
        ax[2].set_ylabel("TAP C")
        ax[3].plot(tapnew['A'])
        ax[3].set_title("WITH IVVC")
        ax[3].set_ylabel("TAP A")
        ax[4].plot(tapnew['B'])
        ax[4].set_ylabel("TAP B")
        ax[5].plot(tapnew['C'])
        ax[5].set_ylabel("TAP C")
        for subplot in range(6):
            ax[subplot].set_ylim(-20, 20)
        f.tight_layout()
        plt.savefig(pJoin(modelDir, "RegulatorTAPpositions.png"))
        #substation voltages
        plt.figure("substation voltage as a function of time")
        f, ax = plt.subplots(6, sharex=True)
        f.set_size_inches(10, 12.0)
        #f.suptitle("voltages at substation NO IVVC")
        ax[0].plot(volt['A'])
        ax[0].set_title('Substation voltages NO IVVC')
        ax[0].set_ylabel('voltage A')
        ax[1].plot(volt['B'])
        ax[1].set_ylabel('voltage B')
        ax[2].plot(volt['C'])
        ax[2].set_ylabel('voltage C')
        ax[3].plot(voltnew['A'])
        ax[3].set_title("WITH IVVC")
        ax[3].set_ylabel('voltage A')
        ax[4].plot(voltnew['B'])
        ax[4].set_ylabel('voltage B')
        ax[5].plot(voltnew['C'])
        ax[5].set_ylabel('voltage C')
        f.tight_layout()
        plt.savefig(pJoin(modelDir, "substationVoltages.png"))
        #cap switches
        plt.figure("capacitor switch state as a function of time")
        f, ax = plt.subplots(6, sharex=True)
        f.set_size_inches(10, 12.0)
        #f.suptitle("Capacitor switch state NO IVVC")
        ax[0].plot(switch['A'])
        ax[0].set_title("Capacitor switch state NO IVVC")
        ax[0].set_ylabel("switch A")
        ax[1].plot(switch['B'])
        ax[1].set_ylabel("switch B")
        ax[2].plot(switch['C'])
        ax[2].set_ylabel("switch C")
        ax[3].plot(switchnew['A'])
        ax[3].set_title("WITH IVVC")
        ax[3].set_ylabel("switch A")
        ax[4].plot(switchnew['B'])
        ax[4].set_ylabel("switch B")
        ax[5].plot(switchnew['C'])
        ax[5].set_ylabel("switch C")
        for subplot in range(6):
            ax[subplot].set_ylim(-2, 2)
        f.tight_layout()
        plt.savefig(pJoin(modelDir, "capacitorSwitch.png"))
        #plt.show()
        #monetization
        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'
        }
        #calculate the month and hour of simulation start and month and hour of simulation end
        simStartTimestamp = simStartDate + " 00:00:00"
        simFormattedDate = datetime.strptime(simStartTimestamp,
                                             "%Y-%m-%d %H:%M:%S")
        simStartMonthNum = int(simFormattedDate.strftime('%m'))
        simstartMonth = monthNames[simStartMonthNum - 1]
        simStartDay = int(simFormattedDate.strftime('%d'))
        if calendar.isleap(int(simFormattedDate.strftime('%Y'))):
            febDays = 29
        else:
            febDays = 28
        monthHours = [
            int(31 * 24),
            int(febDays * 24),
            int(31 * 24),
            int(30 * 24),
            int(31 * 24),
            int(30 * 24),
            int(31 * 24),
            int(31 * 24),
            int(30 * 24),
            int(31 * 24),
            int(30 * 24),
            int(31 * 24)
        ]
        simStartIndex = int(
            sum(monthHours[:(simStartMonthNum - 1)]) + (simStartDay - 1) * 24)
        temp = 0
        cumulHours = [0]
        for x in range(12):
            temp += monthHours[x]
            cumulHours.append(temp)
        for i in range((simStartMonthNum), 13):
            if int(simStartIndex + simRealLength) <= cumulHours[i] and int(
                    simStartIndex + simRealLength) > cumulHours[i - 1]:
                simEndMonthNum = i - 1
                simEndMonth = monthNames[simEndMonthNum]
        # print simstartMonth,simEndMonth
        #calculate peaks for the number of months in simulation
        previndex = 0
        monthPeak = {}
        monthPeakNew = {}
        peakSaveDollars = {}
        energyLostDollars = {}
        lossRedDollars = {}
        simMonthList = monthNames[monthNames.index(simstartMonth):(
            monthNames.index(simEndMonth) + 1)]
        # print simMonthList
        for monthElement in simMonthList:
            # print monthElement
            month = monthNames.index(monthElement)
            index1 = int(previndex)
            index2 = int(min((index1 + int(monthHours[month])), simRealLength))
            monthPeak[monthElement] = max(p[index1:index2]) / 1000.0
            monthPeakNew[monthElement] = max(pnew[index1:index2]) / 1000.0
            peakSaveDollars[monthElement] = (
                monthPeak[monthElement] - monthPeakNew[monthElement]) * float(
                    inData['peakDemandCost' +
                           str(monthToSeason[monthElement]) + 'PerKw'])
            lossRedDollars[monthElement] = (
                sum(realLoss[index1:index2]) / 1000.0 -
                sum(realLossnew[index1:index2]) / 1000.0) * (float(
                    inData['wholesaleEnergyCostPerKwh']))
            energyLostDollars[monthElement] = (
                sum(p[index1:index2]) / 1000.0 - sum(pnew[index1:index2]) /
                1000.0 - sum(realLoss[index1:index2]) / 1000.0 +
                sum(realLossnew[index1:index2]) / 1000.0) * (
                    float(inData['wholesaleEnergyCostPerKwh']) -
                    float(inData['retailEnergyCostPerKwh']))
            previndex = index2
        #money charts
        fig = plt.figure("cost benefit barchart", figsize=(10, 8))
        ticks = range(len(simMonthList))
        ticks1 = [element + 0.15 for element in ticks]
        ticks2 = [element + 0.30 for element in ticks]
        # print ticks
        eld = [energyLostDollars[month] for month in simMonthList]
        lrd = [lossRedDollars[month] for month in simMonthList]
        psd = [peakSaveDollars[month] for month in simMonthList]
        bar_eld = plt.bar(ticks, eld, 0.15, color='red')
        bar_psd = plt.bar(ticks1, psd, 0.15, color='blue')
        bar_lrd = plt.bar(ticks2, lrd, 0.15, color='green')
        plt.legend([bar_eld[0], bar_psd[0], bar_lrd[0]], [
            'energyLostDollars', 'peakReductionDollars', 'lossReductionDollars'
        ],
                   bbox_to_anchor=(0., 1.015, 1., .102),
                   loc=3,
                   ncol=2,
                   mode="expand",
                   borderaxespad=0.1)
        monShort = [element[0:3] for element in simMonthList]
        plt.xticks([t + 0.15 for t in ticks], monShort)
        plt.ylabel('Utility Savings ($)')
        plt.savefig(pJoin(modelDir, "spendChart.png"))
        #cumulative savings graphs
        fig = plt.figure("cost benefit barchart", figsize=(10, 5))
        annualSavings = sum(eld) + sum(lrd) + sum(psd)
        annualSave = lambda x: (annualSavings - float(inData['omCost'])
                                ) * x - float(inData['capitalCost'])
        simplePayback = float(
            inData['capitalCost']) / (annualSavings - float(inData['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"))
        #get exact time stamps from the CSV files generated by Gridlab-D
        timeWithZone = output['Zregulator.csv']['# timestamp']
        timestamps = [element[:19] for element in timeWithZone]
        #data for highcharts
        allOutput["timeStamps"] = timestamps
        allOutput["noCVRPower"] = p
        allOutput["withCVRPower"] = pnew
        allOutput["noCVRLoad"] = whLoads[0]
        allOutput["withCVRLoad"] = whLoads[1]
        allOutput["noCVRLosses"] = whLosses[0]
        allOutput["withCVRLosses"] = whLosses[1]
        allOutput["noCVRTaps"] = tap
        allOutput["withCVRTaps"] = tapnew
        allOutput["noCVRSubVolts"] = volt
        allOutput["withCVRSubVolts"] = voltnew
        allOutput["noCVRCapSwitch"] = switch
        allOutput["withCVRCapSwitch"] = switchnew
        allOutput["noCVRHighVolt"] = highVoltage
        allOutput["withCVRHighVolt"] = highVoltagenew
        allOutput["noCVRLowVolt"] = lowVoltage
        allOutput["withCVRLowVolt"] = lowVoltagenew
        allOutput["noCVRMeanVolt"] = meanVoltage
        allOutput["withCVRMeanVolt"] = meanVoltagenew
        #monetization
        allOutput["simMonthList"] = monShort
        allOutput["energyLostDollars"] = energyLostDollars
        allOutput["lossRedDollars"] = lossRedDollars
        allOutput["peakSaveDollars"] = peakSaveDollars
        allOutput["annualSave"] = [annualSave(x) for x in range(31)]
        # Generate warnings
        #TODO: Timezone adjustment
        try:
            # Check if times for simulation and scada match.
            scadaDates = []
            with open(pJoin(modelDir, "subScadaCalibrated1.player"),
                      "r") as scadaFile:
                for line in scadaFile:
                    (date, val) = line.split(',')
                    scadaDates.append(str(date))
            simFormattedEndDate = simFormattedDate + timedelta(hours=HOURS)
            scadaStartDate = datetime.strptime(scadaDates[0].split(' PST')[0],
                                               "%Y-%m-%d %H:%M:%S")
            scadaEndDate = datetime.strptime(
                scadaDates[len(scadaDates) - 1].split(' PST')[0],
                "%Y-%m-%d %H:%M:%S")
            beginRange = (scadaStartDate - simFormattedDate).total_seconds()
            endRange = (scadaEndDate - simFormattedEndDate).total_seconds()
            # Check if houses exist.
            housesExist, voltageNodeExists = False, False
            for key in localTree:
                if localTree[key].get('object', '') == 'house':
                    housesExist = True
                if localTree[key].get('name',
                                      '') == str(inData.get("voltageNodes",
                                                            0)):
                    voltageNodeExists = True
            if (beginRange > 0.0 or endRange < 0.0) and not housesExist:
                allOutput[
                    "warnings"] = "<strong>WARNING:</strong> The simulation dates entered are not compatible with the scada curve in the feeder."
            # Check if voltage node exists.
            if not voltageNodeExists:
                if allOutput.get('warnings', '') != "":
                    previousWarning = allOutput["warnings"]
                    allOutput[
                        "warnings"] = previousWarning + " The voltage node: " + str(
                            inData.get("voltageNodes",
                                       0)) + " does not exist in the feeder."
                else:
                    allOutput[
                        "warnings"] = "<strong>WARNING:</strong> The voltage node <i>" + str(
                            inData.get(
                                "voltageNodes",
                                0)) + "</i> does not exist in the feeder."
        except:
            pass
        # Update the runTime in the input file.
        endTime = datetime.now()
        inData["runTime"] = str(
            timedelta(seconds=int((endTime - startTime).total_seconds())))
        with open(pJoin(modelDir, "allInputData.json"), "w") as inFile:
            json.dump(inData, inFile, indent=4)
        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 Exception, e:
            pass
        print "DONE RUNNING", modelDir
def runForeground(modelDir, inputDict):
	''' Run the model in its directory. WARNING: GRIDLAB CAN TAKE HOURS TO COMPLETE. '''
	# Check whether model exist or not
	if not os.path.isdir(modelDir):
		os.makedirs(modelDir)
		inputDict["created"] = str(datetime.datetime.now())
	print "STARTING TO RUN", modelDir
	beginTime = datetime.datetime.now()
	feederList = []
	# Get prepare of data and clean workspace if re-run, If re-run remove all the data in the subfolders
	for dirs in os.listdir(modelDir):
		if os.path.isdir(pJoin(modelDir, dirs)):
			shutil.rmtree(pJoin(modelDir, dirs))
	# Get each feeder, prepare data in separate folders, and run there.
	for key in sorted(inputDict, key=inputDict.get):
		if key.startswith("feederName"):
			feederName = inputDict[key]
			feederList.append(feederName)
			try:
				os.remove(pJoin(modelDir, feederName, "allOutputData.json"))
			except Exception, e:
				pass
			if not os.path.isdir(pJoin(modelDir, feederName)):
				os.makedirs(pJoin(modelDir, feederName)) # create subfolders for feeders
			shutil.copy(pJoin(modelDir, feederName + ".omd"),
				pJoin(modelDir, feederName, "feeder.omd"))
			inputDict["climateName"], latforpvwatts = zipCodeToClimateName(inputDict["zipCode"])
			shutil.copy(pJoin(__metaModel__._omfDir, "data", "Climate", inputDict["climateName"] + ".tmy2"),
				pJoin(modelDir, feederName, "climate.tmy2"))
			try:
				startTime = datetime.datetime.now()
				feederJson = json.load(open(pJoin(modelDir, feederName, "feeder.omd")))
				tree = feederJson["tree"]
				# Set up GLM with correct time and recorders:
				feeder.attachRecorders(tree, "Regulator", "object", "regulator")
				feeder.attachRecorders(tree, "Capacitor", "object", "capacitor")
				feeder.attachRecorders(tree, "Inverter", "object", "inverter")
				feeder.attachRecorders(tree, "Windmill", "object", "windturb_dg")
				feeder.attachRecorders(tree, "CollectorVoltage", None, None)
				feeder.attachRecorders(tree, "Climate", "object", "climate")
				feeder.attachRecorders(tree, "OverheadLosses", None, None)
				feeder.attachRecorders(tree, "UndergroundLosses", None, None)
				feeder.attachRecorders(tree, "TriplexLosses", None, None)
				feeder.attachRecorders(tree, "TransformerLosses", None, None)
				feeder.groupSwingKids(tree)
				feeder.adjustTime(tree=tree, simLength=float(inputDict["simLength"]),
					simLengthUnits=inputDict["simLengthUnits"], simStartDate=inputDict["simStartDate"])
				# RUN GRIDLABD IN FILESYSTEM (EXPENSIVE!)
				rawOut = gridlabd.runInFilesystem(tree, attachments=feederJson["attachments"],
					keepFiles=True, workDir=pJoin(modelDir, feederName))
				cleanOut = {}
				# Std Err and Std Out
				cleanOut['stderr'] = rawOut['stderr']
				cleanOut['stdout'] = rawOut['stdout']
				# Time Stamps
				for key in rawOut:
					if '# timestamp' in rawOut[key]:
						cleanOut['timeStamps'] = rawOut[key]['# timestamp']
						break
					elif '# property.. timestamp' in rawOut[key]:
						cleanOut['timeStamps'] = rawOut[key]['# property.. timestamp']
					else:
						cleanOut['timeStamps'] = []
				# Day/Month Aggregation Setup:
				stamps = cleanOut.get('timeStamps',[])
				level = inputDict.get('simLengthUnits','hours')
				# Climate
				for key in rawOut:
					if key.startswith('Climate_') and key.endswith('.csv'):
						cleanOut['climate'] = {}
						cleanOut['climate']['Rain Fall (in/h)'] = hdmAgg(rawOut[key].get('rainfall'), sum, level)
						cleanOut['climate']['Wind Speed (m/s)'] = hdmAgg(rawOut[key].get('wind_speed'), avg, level)
						cleanOut['climate']['Temperature (F)'] = hdmAgg(rawOut[key].get('temperature'), max, level)
						cleanOut['climate']['Snow Depth (in)'] = hdmAgg(rawOut[key].get('snowdepth'), max, level)
						cleanOut['climate']['Direct Insolation (W/m^2)'] = hdmAgg(rawOut[key].get('solar_direct'), sum, level)
				# Voltage Band
				if 'VoltageJiggle.csv' in rawOut:
					cleanOut['allMeterVoltages'] = {}
					cleanOut['allMeterVoltages']['Min'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['min(voltage_12.mag)']], min, level)
					cleanOut['allMeterVoltages']['Mean'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['mean(voltage_12.mag)']], avg, level)
					cleanOut['allMeterVoltages']['StdDev'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['std(voltage_12.mag)']], avg, level)
					cleanOut['allMeterVoltages']['Max'] = hdmAgg([(i / 2) for i in rawOut['VoltageJiggle.csv']['max(voltage_12.mag)']], max, level)
				cleanOut['allMeterVoltages']['stdDevPos'] = [(x+y/2) for x,y in zip(cleanOut['allMeterVoltages']['Mean'], cleanOut['allMeterVoltages']['StdDev'])]
				cleanOut['allMeterVoltages']['stdDevNeg'] = [(x-y/2) for x,y in zip(cleanOut['allMeterVoltages']['Mean'], cleanOut['allMeterVoltages']['StdDev'])]
				# Total # of meters
				count = 0
				with open(pJoin(modelDir, feederName, "feeder.omd")) as f:
					for line in f:
						if "\"objectType\": \"triplex_meter\"" in line:
							count+=1
				print "count=", count
				cleanOut['allMeterVoltages']['triplexMeterCount'] = float(count)
				# Power Consumption
				cleanOut['Consumption'] = {}
				# Set default value to be 0, avoiding missing value when computing Loads
				cleanOut['Consumption']['Power'] = [0] * int(inputDict["simLength"])
				cleanOut['Consumption']['Losses'] = [0] * int(inputDict["simLength"])
				cleanOut['Consumption']['DG'] = [0] * int(inputDict["simLength"])
				for key in rawOut:
					if key.startswith('SwingKids_') and key.endswith('.csv'):
						oneSwingPower = hdmAgg(vecPyth(rawOut[key]['sum(power_in.real)'],rawOut[key]['sum(power_in.imag)']), avg, level)
						if 'Power' not in cleanOut['Consumption']:
							cleanOut['Consumption']['Power'] = oneSwingPower
						else:
							cleanOut['Consumption']['Power'] = vecSum(oneSwingPower,cleanOut['Consumption']['Power'])
					elif key.startswith('Inverter_') and key.endswith('.csv'):
						realA = rawOut[key]['power_A.real']
						realB = rawOut[key]['power_B.real']
						realC = rawOut[key]['power_C.real']
						imagA = rawOut[key]['power_A.imag']
						imagB = rawOut[key]['power_B.imag']
						imagC = rawOut[key]['power_C.imag']
						oneDgPower = hdmAgg(vecSum(vecPyth(realA,imagA),vecPyth(realB,imagB),vecPyth(realC,imagC)), avg, level)
						if 'DG' not in cleanOut['Consumption']:
							cleanOut['Consumption']['DG'] = oneDgPower
						else:
							cleanOut['Consumption']['DG'] = vecSum(oneDgPower,cleanOut['Consumption']['DG'])
					elif key.startswith('Windmill_') and key.endswith('.csv'):
						vrA = rawOut[key]['voltage_A.real']
						vrB = rawOut[key]['voltage_B.real']
						vrC = rawOut[key]['voltage_C.real']
						viA = rawOut[key]['voltage_A.imag']
						viB = rawOut[key]['voltage_B.imag']
						viC = rawOut[key]['voltage_C.imag']
						crB = rawOut[key]['current_B.real']
						crA = rawOut[key]['current_A.real']
						crC = rawOut[key]['current_C.real']
						ciA = rawOut[key]['current_A.imag']
						ciB = rawOut[key]['current_B.imag']
						ciC = rawOut[key]['current_C.imag']
						powerA = vecProd(vecPyth(vrA,viA),vecPyth(crA,ciA))
						powerB = vecProd(vecPyth(vrB,viB),vecPyth(crB,ciB))
						powerC = vecProd(vecPyth(vrC,viC),vecPyth(crC,ciC))
						# HACK: multiply by negative one because turbine power sign is opposite all other DG:
						oneDgPower = [-1.0 * x for x in hdmAgg(vecSum(powerA,powerB,powerC), avg, level)]
						if 'DG' not in cleanOut['Consumption']:
							cleanOut['Consumption']['DG'] = oneDgPower
						else:
							cleanOut['Consumption']['DG'] = vecSum(oneDgPower,cleanOut['Consumption']['DG'])
					elif key in ['OverheadLosses.csv', 'UndergroundLosses.csv', 'TriplexLosses.csv', 'TransformerLosses.csv']:
						realA = rawOut[key]['sum(power_losses_A.real)']
						imagA = rawOut[key]['sum(power_losses_A.imag)']
						realB = rawOut[key]['sum(power_losses_B.real)']
						imagB = rawOut[key]['sum(power_losses_B.imag)']
						realC = rawOut[key]['sum(power_losses_C.real)']
						imagC = rawOut[key]['sum(power_losses_C.imag)']
						oneLoss = hdmAgg(vecSum(vecPyth(realA,imagA),vecPyth(realB,imagB),vecPyth(realC,imagC)), avg, level)
						if 'Losses' not in cleanOut['Consumption']:
							cleanOut['Consumption']['Losses'] = oneLoss
						else:
							cleanOut['Consumption']['Losses'] = vecSum(oneLoss,cleanOut['Consumption']['Losses'])
				# Aggregate up the timestamps:
				if level=='days':
					cleanOut['timeStamps'] = aggSeries(stamps, stamps, lambda x:x[0][0:10], 'days')
				elif level=='months':
					cleanOut['timeStamps'] = aggSeries(stamps, stamps, lambda x:x[0][0:7], 'months')
				# Write the output.
				with open(pJoin(modelDir, feederName, "allOutputData.json"),"w") as outFile:
					json.dump(cleanOut, outFile, indent=4)
				# 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, feederName, "allInputData.json"),"w") as inFile:
					json.dump(inputDict, inFile, indent=4)
				# Clean up the PID file.
				os.remove(pJoin(modelDir, feederName,"PID.txt"))
				print "DONE RUNNING GRIDLABMULTI", modelDir, feederName
			except Exception as e:
				print "MODEL CRASHED GRIDLABMULTI", e, modelDir, feederName
				cancel(pJoin(modelDir, feederName))
				with open(pJoin(modelDir, feederName, "stderr.txt"), "a+") as stderrFile:
					traceback.print_exc(file = stderrFile)
Example #13
0
def attachVolts(workDir, feederPath, voltVectorA, voltVectorB, voltVectorC, simStartDate, simLength, simLengthUnits):
	'''read voltage vectors of 3 different phases, run gridlabd, and attach output to the feeder.'''
	try:
		timeStamp = [simStartDate['Date']]
		for x in range (1, 8760):
			timeStamp.append(timeStamp[x-1] + dt.timedelta(hours=1))
		firstDateTime = timeStamp[1]
		with open(pJoin(pJoin(workDir,"gridlabD"),"phaseAVoltage.player"),"w") as voltFile:
			for x in range(0, 8760):
				timestamp = timeStamp[x]
				voltage = str("%0.2f"%float(voltVectorA[x]))+"+0j"
				line = timestamp.strftime("%Y-%m-%d %H:%M:%S") + " " + simStartDate['timeZone'] + "," + str(voltage) + "\n"
				voltFile.write(line)
		with open(pJoin(pJoin(workDir,"gridlabD"),"phaseBVoltage.player"),"w") as voltFile:
			for x in range(0, 8760):
				timestamp = timeStamp[x]
				voltage = str("%0.2f"%float(voltVectorB[x]))+"-"+str("%0.4f"%float(random.uniform(6449,6460)))+"j"
				line = timestamp.strftime("%Y-%m-%d %H:%M:%S") + " " + simStartDate['timeZone'] + "," + str(voltage) + "\n"
				voltFile.write(line)
		with open(pJoin(pJoin(workDir,"gridlabD"),"phaseCVoltage.player"),"w") as voltFile:
			for x in range(0, 8760):
				timestamp = timeStamp[x]
				voltage = str("%0.2f"%float(voltVectorC[x]))+"+"+str("%0.4f"%float(random.uniform(6449,6460)))+"j"
				line = timestamp.strftime("%Y-%m-%d %H:%M:%S") + " " + simStartDate['timeZone'] + "," + str(voltage) + "\n"
				voltFile.write(line)
		with open(feederPath, "r") as jsonIn:
			feederJson = json.load(jsonIn)
			tree = feederJson.get("tree", {})
		# Find swingNode name.
		for key in tree:
			if tree[key].get('bustype','').lower() == 'swing':
				swingName = tree[key].get('name')
		# Attach player.
		classOb = {'omftype':'class player','argument':'{double value;}'}
		voltageObA = {"object":"player", "property":"voltage_A", "file":"phaseAVoltage.player", "loop":"0", "parent":swingName}
		voltageObB = {"object":"player", "property":"voltage_B", "file":"phaseBVoltage.player", "loop":"0", "parent":swingName}
		voltageObC = {"object":"player", "property":"voltage_C", "file":"phaseCVoltage.player", "loop":"0", "parent":swingName}
		maxKey = feeder.getMaxKey(tree)
		voltplayerKeyA = maxKey + 2
		voltplayerKeyB = maxKey + 3
		voltplayerKeyC = maxKey + 4
		tree[maxKey+1] = classOb
		tree[voltplayerKeyA] = voltageObA
		tree[voltplayerKeyB] = voltageObB
		tree[voltplayerKeyC] = voltageObC
		# Adjust time and run output.
		feeder.adjustTime(tree, simLength, simLengthUnits, firstDateTime.strftime("%Y-%m-%d %H:%M:%S"))
		output = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=pJoin(workDir,"gridlabD"))
		# Write the output.
		with open(pJoin(workDir,"calibratedFeeder.omd"),"w") as outJson:
			playerStringA = open(pJoin(pJoin(workDir,"gridlabD"),"phaseAVoltage.player")).read()
			playerStringB = open(pJoin(pJoin(workDir,"gridlabD"),"phaseBVoltage.player")).read()
			playerStringC = open(pJoin(pJoin(workDir,"gridlabD"),"phaseCVoltage.player")).read()
			feederJson["attachments"]["phaseAVoltage.player"] = playerStringA
			feederJson["attachments"]["phaseBVoltage.player"] = playerStringB
			feederJson["attachments"]["phaseCVoltage.player"] = playerStringC
			feederJson["tree"] = tree
			json.dump(feederJson, outJson, indent=4)
		return pJoin(workDir,"calibratedFeeder.omd"), True
	except:
		print "Failed to run gridlabD with voltage players."
		return "", False
Example #14
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)
Example #15
0
def runModel(modelDir,localTree,inData):
	'''This reads a glm file, changes the method of powerflow and reruns'''
	try:
		os.remove(pJoin(modelDir,"allOutputData.json"))
	except:
		pass
	allOutput = {}
	if not os.path.isdir(modelDir):
		os.makedirs(modelDir)
		inData["created"] = str(datetime.now())
	with open(pJoin(modelDir,"allInputData.json"),"w") as inputFile:
		json.dump(inData, inputFile, indent=4)
	binaryName = "gridlabd"
	for key in localTree:
		if "solver_method" in localTree[key].keys():
			print "current solver method", localTree[key]["solver_method"] 
			localTree[key]["solver_method"] = 'FBS'
	#find the swing bus and recorder attached to substation
	for key in localTree:
		if localTree[key].get('bustype','').lower() == 'swing':
			swingIndex = key
			swingName = localTree[key].get('name')
		if localTree[key].get('object','') == 'regulator' and localTree[key].get('from','') == swingName:
			regIndex = key
			regConfName = localTree[key]['configuration']
	#find the regulator and capacitor names and combine to form a string for volt-var control object
	regKeys = []
	accum_reg = ""
	for key in localTree:
		if localTree[key].get("object","") == "regulator":
			accum_reg += localTree[key].get("name","ERROR") + ","
			regKeys.append(key)
	regstr = accum_reg[:-1]
	print regKeys
	capKeys = []
	accum_cap = ""
	for key in localTree:
		if localTree[key].get("object","") == "capacitor":
			accum_cap += localTree[key].get("name","ERROR") + ","
			capKeys.append(key)
			if localTree[key].get("control","").lower() == "manual":
				localTree[key]['control'] = "VOLT"
				print "changing capacitor control from manual to volt"
	capstr = accum_cap[:-1]
	print capKeys
	# 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': localTree[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': localTree[swingIndex]['name'],
			'property': 'voltage_A,voltage_B,voltage_C'},
			{'object': 'recorder',
			'file': 'ZsubstationBottom.csv',
			'limit': '0',
			'parent': localTree[regIndex]['to'],
			'property': 'voltage_A,voltage_B,voltage_C'}]
	#recorder object for capacitor switching - if capacitors exist
	if capKeys != []:
		for key in capKeys:
			recorders.append({'object': 'recorder',
			'file': 'ZcapSwitch' + str(key) + '.csv',
			'limit': '0',
			'parent': localTree[key]['name'],
			'property': 'switchA,switchB,switchC'})
	#attach recorder process
	biggest = 1 + max([int(k) for k in localTree.keys()])
	for index, rec in enumerate(recorders):
		localTree[biggest + index] = rec
	#run a reference load flow
	HOURS = float(100)
	year_lp = False   #leap year
	feeder.adjustTime(localTree,HOURS,"hours","2011-01-01")	
	output = gridlabd.runInFilesystem(localTree,keepFiles=False,workDir=modelDir)
	os.remove(pJoin(modelDir,"PID.txt"))
	p = output['Zregulator.csv']['power_in.real']
	q = output['Zregulator.csv']['power_in.imag']
	#time delays from configuration files
	time_delay_reg = '30.0'  
	time_delay_cap = '300.0'
	for key in localTree:
		if localTree[key].get('object','') == "regulator_configuration":
			time_delay_reg = localTree[key]['time_delay']
			print "time_delay_reg",time_delay_reg
		# if localTree[key].get('object','') == "capacitor":
		# 	time_delay_cap = localTree[key]['time_delay']
		# 	print "time_delay_cap",time_delay_cap
	#change the recorder names
	for key in localTree:
		if localTree[key].get('object','') == "collector" or localTree[key].get('object','') == "recorder":
			if localTree[key].get('file','').startswith('Z'):
				localTree[key]['file'] = localTree[key].get('file','').replace('Z','NewZ')
	#create volt-var control object
	max_key = max([int(key) for key in localTree.keys()])
	print max_key
	localTree[max_key+1] = {'object' : 'volt_var_control',
	'name' : 'IVVC1',
	'control_method' : 'ACTIVE',
	'capacitor_delay' : str(time_delay_cap),
	'regulator_delay' : str(time_delay_reg),
	'desired_pf' : '0.99',
	'd_max' : '0.6',
	'd_min' : '0.1',
	'substation_link' : str(localTree[regIndex]['name']),
	'regulator_list' : regstr,
	'capacitor_list': capstr} 
	#running powerflow analysis via gridalab after attaching a regulator
	feeder.adjustTime(localTree,HOURS,"hours","2011-01-01")	
	output1 = gridlabd.runInFilesystem(localTree,keepFiles=True,workDir=modelDir)
	os.remove(pJoin(modelDir,"PID.txt"))
	pnew = output1['NewZregulator.csv']['power_in.real']
	qnew = output1['NewZregulator.csv']['power_in.imag']
	#total real and imaginary losses as a function of time
	realLoss = []
	imagLoss = []
	realLossnew = []
	imagLossnew = []
	for element in range(int(HOURS)):
		r = 0.0
		i = 0.0
		rnew = 0.0
		inew = 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)'][element]
				i += output[device]['sum(power_losses_' + letter + '.imag)'][element]
				rnew += output1['New'+device]['sum(power_losses_' + letter + '.real)'][element]
				inew += output1['New'+device]['sum(power_losses_' + letter + '.imag)'][element]
		realLoss.append(r)
		imagLoss.append(i)
		realLossnew.append(rnew)
		imagLossnew.append(inew)
	#voltage calculations and tap calculations
	lowVoltage = []
	meanVoltage = []
	highVoltage = []
	lowVoltagenew = []
	meanVoltagenew = []
	highVoltagenew = []
	tap = {'A':[],'B':[],'C':[]}
	tapnew = {'A':[],'B':[],'C':[]}
	volt = {'A':[],'B':[],'C':[]}
	voltnew = {'A':[],'B':[],'C':[]}
	switch = {'A':[],'B':[],'C':[]}
	switchnew = {'A':[],'B':[],'C':[]}
	for element in range(int(HOURS)):
		for letter in ['A','B','C']:
			tap[letter].append(output['Zregulator.csv']['tap_' + letter][element])
			tapnew[letter].append(output1['NewZregulator.csv']['tap_' + letter][element])
			#voltage real, imag
			vr, vi = sepRealImag(output['ZsubstationBottom.csv']['voltage_'+letter][element])
			volt[letter].append(math.sqrt(vr**2+vi**2)/60)
			vrnew, vinew = sepRealImag(output1['NewZsubstationBottom.csv']['voltage_'+letter][element])
			voltnew[letter].append(math.sqrt(vrnew**2+vinew**2)/60)
			if capKeys != []:
				switch[letter].append(output['ZcapSwitch' + str(int(capKeys[0])) + '.csv']['switch'+ letter][element])
				switchnew[letter].append(output1['NewZcapSwitch' + str(int(capKeys[0])) + '.csv']['switch'+ letter][element])
		lowVoltage.append(float(output['ZvoltageJiggle.csv']['min(voltage_12.mag)'][element])/2.0)
		meanVoltage.append(float(output['ZvoltageJiggle.csv']['mean(voltage_12.mag)'][element])/2.0)
		highVoltage.append(float(output['ZvoltageJiggle.csv']['max(voltage_12.mag)'][element])/2.0)
		lowVoltagenew.append(float(output1['NewZvoltageJiggle.csv']['min(voltage_12.mag)'][element])/2.0)
		meanVoltagenew.append(float(output1['NewZvoltageJiggle.csv']['mean(voltage_12.mag)'][element])/2.0)
		highVoltagenew.append(float(output1['NewZvoltageJiggle.csv']['max(voltage_12.mag)'][element])/2.0)
	#energy calculations
	whEnergy = []
	whLosses = []
	whLoads = []
	whEnergy.append(sum(p)/10**6)
	whLosses.append(sum(realLoss)/10**6)
	whLoads.append((sum(p)-sum(realLoss))/10**6)
	whEnergy.append(sum(pnew)/10**6)
	whLosses.append(sum(realLossnew)/10**6)
	whLoads.append((sum(pnew)-sum(realLossnew))/10**6)
	indices = ['No IVVC', 'With IVVC']
	# energySalesRed = (whLoads[1]-whLoads[0])*(inData['wholesaleEnergyCostPerKwh'])*1000
	# lossSav = (whLosses[0]-whLosses[1])*inData['wholesaleEnergyCostPerKwh']*1000
	# print energySalesRed, lossSav
	#plots
	ticks = []
	plt.clf()
	plt.title("total energy")
	plt.ylabel("total load and losses (MWh)")
	for element in range(2):
		ticks.append(element)
		bar_loss = plt.bar(element, whLosses[element], 0.15, color= 'red')
		bar_load = plt.bar(element+0.15, whLoads[element], 0.15, color= 'orange')
	plt.legend([bar_load[0],bar_loss[0]],['total load', 'total losses'],bbox_to_anchor=(0., 0.915, 1., .102), loc=3,
		       ncol=2, mode="expand", borderaxespad=0.1)
	plt.xticks([t+0.15 for t in ticks],indices)
	plt.savefig(pJoin(modelDir,"total energy.png"))
	#real and imaginary power
	plt.figure("real power")
	plt.title("Real Power at substation")
	plt.ylabel("substation real power (MW)")
	pMW = [element/10**6 for element in p]
	pMWn = [element/10**6 for element in pnew]
	pw = plt.plot(pMW)
	npw = plt.plot(pMWn)
	plt.legend([pw[0], npw[0]], ['NO IVVC','WITH IVVC'],bbox_to_anchor=(0., 0.915, 1., .102), loc=3,
		ncol=2, mode="expand", borderaxespad=0.1)
	plt.savefig(pJoin(modelDir,"real power.png"))
	plt.figure("Reactive power")
	plt.title("Reactive Power at substation")
	plt.ylabel("substation reactive power (MVAR)")
	qMVAR = [element/10**6 for element in q]
	qMVARn = [element/10**6 for element in qnew]
	iw = plt.plot(qMVAR)
	niw = plt.plot(qMVARn)
	plt.legend([iw[0], niw[0]], ['NO IVVC','WITH IVVC'],bbox_to_anchor=(0., 0.915, 1., .102), loc=3,
		ncol=2, mode="expand", borderaxespad=0.1)
	plt.savefig(pJoin(modelDir,"imaginary power.png"))
	#voltage plots
	plt.figure("voltages as a function of time")
	f,ax = plt.subplots(2,sharex=True)
	f.suptitle("Voltages high and low")
	lv = ax[0].plot(lowVoltage,color = 'cadetblue')
	mv = ax[0].plot(meanVoltage,color = 'blue')
	hv = ax[0].plot(highVoltage, color = 'cadetblue')
	ax[0].legend([lv[0], mv[0], hv[0]], ['low voltage','mean voltage','high voltage'],bbox_to_anchor=(0., 0.915, 1., .1), loc=3,
		ncol=3, mode="expand", borderaxespad=0.1)
	ax[0].set_ylabel('NO IVVC')
	nlv = ax[1].plot(lowVoltagenew,color = 'cadetblue')
	nmv = ax[1].plot(meanVoltagenew,color = 'blue')
	nhv = ax[1].plot(highVoltagenew, color = 'cadetblue')
	ax[1].set_ylabel('WITH IVVC')
	plt.savefig(pJoin(modelDir,"Voltages.png"))
	#tap positions
	plt.figure("TAP positions NO IVVC")
	f,ax = plt.subplots(6,sharex=True)
	f.set_size_inches(18.5,12.0)
	#f.suptitle("Regulator Tap positions")
	ax[0].plot(tap['A'])
	ax[0].set_title("Regulator Tap positions NO IVVC")
	ax[0].set_ylabel("TAP A")
	ax[1].plot(tap['B'])
	ax[1].set_ylabel("TAP B")
	ax[2].plot(tap['C'])
	ax[2].set_ylabel("TAP C")
	ax[3].plot(tapnew['A'])
	ax[3].set_title("WITH IVVC")
	ax[3].set_ylabel("TAP A")
	ax[4].plot(tapnew['B'])
	ax[4].set_ylabel("TAP B")
	ax[5].plot(tapnew['C'])
	ax[5].set_ylabel("TAP C")
	for subplot in range(6):
		ax[subplot].set_ylim(-20,20)
	f.tight_layout()
	plt.savefig(pJoin(modelDir,"Regulator TAP positions.png"))
	#substation voltages
	plt.figure("substation voltage as a function of time")
	f,ax = plt.subplots(6,sharex=True)
	f.set_size_inches(18.5,12.0)
	#f.suptitle("voltages at substation NO IVVC")
	ax[0].plot(volt['A'])
	ax[0].set_title('Substation voltages NO IVVC')
	ax[0].set_ylabel('voltage A')
	ax[1].plot(volt['B'])
	ax[1].set_ylabel('voltage B')
	ax[2].plot(volt['C'])
	ax[2].set_ylabel('voltage C')
	ax[3].plot(voltnew['A'])
	ax[3].set_title("WITH IVVC")
	ax[3].set_ylabel('voltage A')
	ax[4].plot(voltnew['B'])
	ax[4].set_ylabel('voltage B')
	ax[5].plot(voltnew['C'])
	ax[5].set_ylabel('voltage C')
	f.tight_layout()
	plt.savefig(pJoin(modelDir,"substation voltages.png"))
	#cap switches - plotted if capacitors are present
	if capKeys != []:
		plt.figure("capacitor switch state as a function of time")
		f,ax = plt.subplots(6,sharex=True)
		f.set_size_inches(18.5,12.0)
		#f.suptitle("Capacitor switch state NO IVVC")
		ax[0].plot(switch['A'])
		ax[0].set_title("Capacitor switch state NO IVVC")
		ax[0].set_ylabel("switch A")
		ax[1].plot(switch['B'])
		ax[1].set_ylabel("switch B")
		ax[2].plot(switch['C'])
		ax[2].set_ylabel("switch C")
		ax[3].plot(switchnew['A'])
		ax[3].set_title("WITH IVVC")
		ax[3].set_ylabel("switch A")
		ax[4].plot(switchnew['B'])
		ax[4].set_ylabel("switch B")
		ax[5].plot(switchnew['C'])
		ax[5].set_ylabel("switch C")
		for subplot in range(6):
			ax[subplot].set_ylim(-2,2)
		f.tight_layout()
		plt.savefig(pJoin(modelDir,"capacitor switch.png"))
	#plt.show()
	#monetization
	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'}
	if year_lp == True:
		febDays = 29
	else:
		febDays = 28
	monthHours = [int(31*24),int(febDays*24),int(31*24),int(30*24),int(31*24),int(30*24),int(31*24),int(31*24),int(30*24),int(31*24),int(30*24),int(31*24)]
	#find simulation months
	temp = 0
	cumulHours = []
	for x in range(12):
		temp += monthHours[x]
		cumulHours.append(temp)
	for i in range(12):
		if i == 0:
			lowval = 0
		else:
			lowval = cumulHours[i-1]
		if HOURS<=cumulHours[i] and HOURS>=lowval:
			hourMonth = monthNames[i]
			hourIndex = i
	#calculate peaks for the number of months in simulation
	previndex = 0
	monthPeak = {}
	monthPeakNew = {}
	peakSaveDollars = {}
	energyLostDollars = {}
	lossRedDollars = {}
	for month in range(hourIndex+1):
		index1 = int(previndex)
		index2 = int(min((index1 + int(monthHours[month])), HOURS))
		monthPeak[monthNames[month]] = max(p[index1:index2])/1000.0
		monthPeakNew[monthNames[month]] = max(pnew[index1:index2])/1000.0
		peakSaveDollars[monthNames[month]] = (monthPeak[monthNames[month]]-monthPeakNew[monthNames[month]])*inData['peakDemandCost'+str(monthToSeason[monthNames[month]])+'PerKw']
		lossRedDollars[monthNames[month]] = (sum(realLoss[index1:index2])/1000.0 - sum(realLossnew[index1:index2])/1000.0)*(inData['wholesaleEnergyCostPerKwh'])
		energyLostDollars[monthNames[month]] = (sum(p[index1:index2])/1000.0  - sum(pnew[index1:index2])/1000.0  - sum(realLoss[index1:index2])/1000.0  
			+ sum(realLossnew[index1:index2])/1000.0 )*(inData['wholesaleEnergyCostPerKwh'] - inData['retailEnergyCostPerKwh'])
		previndex = index2
	#money charts
	simMonths = monthNames[:hourIndex+1]
	fig = plt.figure("cost benefit barchart",figsize=(10,8))
	ticks = range(len(simMonths))
	ticks1 = [element+0.15 for element in ticks]
	ticks2 = [element+0.30 for element in ticks]
	print ticks
	eld = [energyLostDollars[month] for month in simMonths]
	lrd = [lossRedDollars[month] for month in simMonths]
	psd = [peakSaveDollars[month] for month in simMonths]
	bar_eld = plt.bar(ticks,eld,0.15,color='red') 
	bar_psd = plt.bar(ticks1,psd,0.15,color='blue')
	bar_lrd = plt.bar(ticks2,lrd,0.15,color='green')
	plt.legend([bar_eld[0], bar_psd[0], bar_lrd[0]], ['energyLostDollars','peakReductionDollars','lossReductionDollars'],bbox_to_anchor=(0., 1.015, 1., .102), loc=3,
		ncol=2, mode="expand", borderaxespad=0.1)
	monShort = [element[0:3] for element in simMonths]
	plt.xticks([t+0.15 for t in ticks],monShort)
	plt.ylabel('Utility Savings ($)')
	plt.savefig(pJoin(modelDir,"spendChart.png"))
	with open(pJoin(modelDir,"spendChart.png"),"rb") as inFile:
		allOutput["spendChart"] = inFile.read().encode("base64")
	#cumulative savings graphs
	fig = plt.figure("cost benefit barchart",figsize=(10,5))
	annualSavings = sum(eld) + sum(lrd) + sum(psd)
	annualSave = lambda x:(annualSavings - inData['omCost']) * x - inData['capitalCost']
	simplePayback = inData['capitalCost']/(annualSavings - inData['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"))
	with open(pJoin(modelDir,"savingsChart.png"),"rb") as inFile:
		allOutput["savingsChart"] = inFile.read().encode("base64")
	# Update the runTime in the input file.
	# endTime = datetime.now()
	# inDat["runTime"] = str(timedelta(seconds=int((endTime - startTime).total_seconds())))
	with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
		json.dump(inData, inFile, indent=4)
	with open(pJoin(modelDir,"allOutputData.json"),"w") as outFile:
		json.dump(allOutput, outFile, indent=4)
	print "DONE RUNNING", modelDir
Example #16
0
def heavyProcessing(modelDir, inputDict):
    ''' Run the model in its directory. WARNING: GRIDLAB CAN TAKE HOURS TO COMPLETE. '''
    print "STARTING TO RUN", modelDir
    beginTime = datetime.datetime.now()
    # Get feeder name and data in.
    try:
        os.mkdir(pJoin(modelDir, 'gldContainer'))
    except:
        pass
    feederDir, feederName = inputDict["feederName"].split("___")
    shutil.copy(
        pJoin(__metaModel__._omfDir, "data", "Feeder", feederDir,
              feederName + ".json"), pJoin(modelDir, "feeder.json"))
    shutil.copy(
        pJoin(__metaModel__._omfDir, "data", "Climate",
              inputDict["climateName"] + ".tmy2"),
        pJoin(modelDir, "gldContainer", "climate.tmy2"))
    try:
        startTime = datetime.datetime.now()
        feederJson = json.load(open(pJoin(modelDir, "feeder.json")))
        tree = feederJson["tree"]
        # Set up GLM with correct time and recorders:
        feeder.attachRecorders(tree, "Regulator", "object", "regulator")
        feeder.attachRecorders(tree, "Capacitor", "object", "capacitor")
        feeder.attachRecorders(tree, "Inverter", "object", "inverter")
        feeder.attachRecorders(tree, "Windmill", "object", "windturb_dg")
        feeder.attachRecorders(tree, "CollectorVoltage", None, None)
        feeder.attachRecorders(tree, "Climate", "object", "climate")
        feeder.attachRecorders(tree, "OverheadLosses", None, None)
        feeder.attachRecorders(tree, "UndergroundLosses", None, None)
        feeder.attachRecorders(tree, "TriplexLosses", None, None)
        feeder.attachRecorders(tree, "TransformerLosses", None, None)
        feeder.groupSwingKids(tree)
        # Attach recorders for system voltage map:
        stub = {
            'object': 'group_recorder',
            'group': '"class=node"',
            'property': 'voltage_A',
            'interval': 3600,
            'file': 'aVoltDump.csv'
        }
        for phase in ['A', 'B', 'C']:
            copyStub = dict(stub)
            copyStub['property'] = 'voltage_' + phase
            copyStub['file'] = phase.lower() + 'VoltDump.csv'
            tree[feeder.getMaxKey(tree) + 1] = copyStub
        feeder.adjustTime(tree=tree,
                          simLength=float(inputDict["simLength"]),
                          simLengthUnits=inputDict["simLengthUnits"],
                          simStartDate=inputDict["simStartDate"])
        # RUN GRIDLABD IN FILESYSTEM (EXPENSIVE!)
        rawOut = gridlabd.runInFilesystem(
            tree,
            attachments=feederJson["attachments"],
            keepFiles=True,
            workDir=pJoin(modelDir, 'gldContainer'))
        cleanOut = {}
        # Std Err and Std Out
        cleanOut['stderr'] = rawOut['stderr']
        cleanOut['stdout'] = rawOut['stdout']
        # Time Stamps
        for key in rawOut:
            if '# timestamp' in rawOut[key]:
                cleanOut['timeStamps'] = rawOut[key]['# timestamp']
                break
            elif '# property.. timestamp' in rawOut[key]:
                cleanOut['timeStamps'] = rawOut[key]['# property.. timestamp']
            else:
                cleanOut['timeStamps'] = []
        # Day/Month Aggregation Setup:
        stamps = cleanOut.get('timeStamps', [])
        level = inputDict.get('simLengthUnits', 'hours')
        # Climate
        for key in rawOut:
            if key.startswith('Climate_') and key.endswith('.csv'):
                cleanOut['climate'] = {}
                cleanOut['climate']['Rain Fall (in/h)'] = hdmAgg(
                    rawOut[key].get('rainfall'), sum, level)
                cleanOut['climate']['Wind Speed (m/s)'] = hdmAgg(
                    rawOut[key].get('wind_speed'), avg, level)
                cleanOut['climate']['Temperature (F)'] = hdmAgg(
                    rawOut[key].get('temperature'), max, level)
                cleanOut['climate']['Snow Depth (in)'] = hdmAgg(
                    rawOut[key].get('snowdepth'), max, level)
                cleanOut['climate']['Direct Normal (W/sf)'] = hdmAgg(
                    rawOut[key].get('solar_direct'), sum, level)
                #cleanOut['climate']['Global Horizontal (W/sf)'] = hdmAgg(rawOut[key].get('solar_global'), sum, level)
                climateWbySFList = hdmAgg(rawOut[key].get('solar_global'), sum,
                                          level)
                #converting W/sf to W/sm
                climateWbySMList = [x * 10.76392 for x in climateWbySFList]
                cleanOut['climate'][
                    'Global Horizontal (W/sm)'] = climateWbySMList
        # Voltage Band
        if 'VoltageJiggle.csv' in rawOut:
            cleanOut['allMeterVoltages'] = {}
            cleanOut['allMeterVoltages']['Min'] = hdmAgg([
                float(i / 2)
                for i in rawOut['VoltageJiggle.csv']['min(voltage_12.mag)']
            ], min, level)
            cleanOut['allMeterVoltages']['Mean'] = hdmAgg([
                float(i / 2)
                for i in rawOut['VoltageJiggle.csv']['mean(voltage_12.mag)']
            ], avg, level)
            cleanOut['allMeterVoltages']['StdDev'] = hdmAgg([
                float(i / 2)
                for i in rawOut['VoltageJiggle.csv']['std(voltage_12.mag)']
            ], avg, level)
            cleanOut['allMeterVoltages']['Max'] = hdmAgg([
                float(i / 2)
                for i in rawOut['VoltageJiggle.csv']['max(voltage_12.mag)']
            ], max, level)
        # Power Consumption
        cleanOut['Consumption'] = {}
        # Set default value to be 0, avoiding missing value when computing Loads
        cleanOut['Consumption']['Power'] = [0] * int(inputDict["simLength"])
        cleanOut['Consumption']['Losses'] = [0] * int(inputDict["simLength"])
        cleanOut['Consumption']['DG'] = [0] * int(inputDict["simLength"])
        for key in rawOut:
            if key.startswith('SwingKids_') and key.endswith('.csv'):
                oneSwingPower = hdmAgg(
                    vecPyth(rawOut[key]['sum(power_in.real)'],
                            rawOut[key]['sum(power_in.imag)']), avg, level)
                if 'Power' not in cleanOut['Consumption']:
                    cleanOut['Consumption']['Power'] = oneSwingPower
                else:
                    cleanOut['Consumption']['Power'] = vecSum(
                        oneSwingPower, cleanOut['Consumption']['Power'])
            elif key.startswith('Inverter_') and key.endswith('.csv'):
                realA = rawOut[key]['power_A.real']
                realB = rawOut[key]['power_B.real']
                realC = rawOut[key]['power_C.real']
                imagA = rawOut[key]['power_A.imag']
                imagB = rawOut[key]['power_B.imag']
                imagC = rawOut[key]['power_C.imag']
                oneDgPower = hdmAgg(
                    vecSum(vecPyth(realA, imagA), vecPyth(realB, imagB),
                           vecPyth(realC, imagC)), avg, level)
                if 'DG' not in cleanOut['Consumption']:
                    cleanOut['Consumption']['DG'] = oneDgPower
                else:
                    cleanOut['Consumption']['DG'] = vecSum(
                        oneDgPower, cleanOut['Consumption']['DG'])
            elif key.startswith('Windmill_') and key.endswith('.csv'):
                vrA = rawOut[key]['voltage_A.real']
                vrB = rawOut[key]['voltage_B.real']
                vrC = rawOut[key]['voltage_C.real']
                viA = rawOut[key]['voltage_A.imag']
                viB = rawOut[key]['voltage_B.imag']
                viC = rawOut[key]['voltage_C.imag']
                crB = rawOut[key]['current_B.real']
                crA = rawOut[key]['current_A.real']
                crC = rawOut[key]['current_C.real']
                ciA = rawOut[key]['current_A.imag']
                ciB = rawOut[key]['current_B.imag']
                ciC = rawOut[key]['current_C.imag']
                powerA = vecProd(vecPyth(vrA, viA), vecPyth(crA, ciA))
                powerB = vecProd(vecPyth(vrB, viB), vecPyth(crB, ciB))
                powerC = vecProd(vecPyth(vrC, viC), vecPyth(crC, ciC))
                oneDgPower = hdmAgg(vecSum(powerA, powerB, powerC), avg, level)
                if 'DG' not in cleanOut['Consumption']:
                    cleanOut['Consumption']['DG'] = oneDgPower
                else:
                    cleanOut['Consumption']['DG'] = vecSum(
                        oneDgPower, cleanOut['Consumption']['DG'])
            elif key in [
                    'OverheadLosses.csv', 'UndergroundLosses.csv',
                    'TriplexLosses.csv', 'TransformerLosses.csv'
            ]:
                realA = rawOut[key]['sum(power_losses_A.real)']
                imagA = rawOut[key]['sum(power_losses_A.imag)']
                realB = rawOut[key]['sum(power_losses_B.real)']
                imagB = rawOut[key]['sum(power_losses_B.imag)']
                realC = rawOut[key]['sum(power_losses_C.real)']
                imagC = rawOut[key]['sum(power_losses_C.imag)']
                oneLoss = hdmAgg(
                    vecSum(vecPyth(realA, imagA), vecPyth(realB, imagB),
                           vecPyth(realC, imagC)), avg, level)
                if 'Losses' not in cleanOut['Consumption']:
                    cleanOut['Consumption']['Losses'] = oneLoss
                else:
                    cleanOut['Consumption']['Losses'] = vecSum(
                        oneLoss, cleanOut['Consumption']['Losses'])
            elif key.startswith('Regulator_') and key.endswith('.csv'):
                #split function to strip off .csv from filename and user rest of the file name as key. for example- Regulator_VR10.csv -> key would be Regulator_VR10
                regName = ""
                regName = key
                newkey = regName.split(".")[0]
                cleanOut[newkey] = {}
                cleanOut[newkey]['RegTapA'] = [0] * int(inputDict["simLength"])
                cleanOut[newkey]['RegTapB'] = [0] * int(inputDict["simLength"])
                cleanOut[newkey]['RegTapC'] = [0] * int(inputDict["simLength"])
                cleanOut[newkey]['RegTapA'] = rawOut[key]['tap_A']
                cleanOut[newkey]['RegTapB'] = rawOut[key]['tap_B']
                cleanOut[newkey]['RegTapC'] = rawOut[key]['tap_C']
                cleanOut[newkey]['RegPhases'] = rawOut[key]['phases'][0]
            elif key.startswith('Capacitor_') and key.endswith('.csv'):
                capName = ""
                capName = key
                newkey = capName.split(".")[0]
                cleanOut[newkey] = {}
                cleanOut[newkey]['Cap1A'] = [0] * int(inputDict["simLength"])
                cleanOut[newkey]['Cap1B'] = [0] * int(inputDict["simLength"])
                cleanOut[newkey]['Cap1C'] = [0] * int(inputDict["simLength"])
                cleanOut[newkey]['Cap1A'] = rawOut[key]['switchA']
                cleanOut[newkey]['Cap1B'] = rawOut[key]['switchB']
                cleanOut[newkey]['Cap1C'] = rawOut[key]['switchC']
                cleanOut[newkey]['CapPhases'] = rawOut[key]['phases'][0]
        # What percentage of our keys have lat lon data?
        latKeys = [
            tree[key]['latitude'] for key in tree if 'latitude' in tree[key]
        ]
        latPerc = 1.0 * len(latKeys) / len(tree)
        if latPerc < 0.25: doNeato = True
        else: doNeato = False
        # Generate the frames for the system voltage map time traveling chart.
        genTime = generateVoltChart(tree,
                                    rawOut,
                                    modelDir,
                                    neatoLayout=doNeato)
        cleanOut['genTime'] = genTime
        # Aggregate up the timestamps:
        if level == 'days':
            cleanOut['timeStamps'] = aggSeries(stamps, stamps,
                                               lambda x: x[0][0:10], 'days')
        elif level == 'months':
            cleanOut['timeStamps'] = aggSeries(stamps, stamps,
                                               lambda x: x[0][0:7], 'months')
        # Write the output.
        with open(pJoin(modelDir, "allOutputData.json"), "w") as outFile:
            json.dump(cleanOut, outFile, indent=4)
        # 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)
        # Clean up the PID file.
        os.remove(pJoin(modelDir, "gldContainer", "PID.txt"))
        print "DONE RUNNING", modelDir
    except Exception as e:
        print "MODEL CRASHED", e
        # Cancel to get rid of extra background processes.
        try:
            os.remove(pJoin(modelDir, 'PPID.txt'))
        except:
            pass
        thisErr = traceback.format_exc()
        inputDict['stderr'] = thisErr
        with open(os.path.join(modelDir, 'stderr.txt'), 'w') as errorFile:
            errorFile.write(thisErr)
        # Dump input with error included.
        with open(pJoin(modelDir, "allInputData.json"), "w") as inFile:
            json.dump(inputDict, inFile, indent=4)
    finishTime = datetime.datetime.now()
    inputDict["runTime"] = str(
        datetime.timedelta(seconds=int((finishTime -
                                        beginTime).total_seconds())))
    with open(pJoin(modelDir, "allInputData.json"), "w") as inFile:
        json.dump(inputDict, inFile, indent=4)
    try:
        os.remove(pJoin(modelDir, "PPID.txt"))
    except:
        pass
Example #17
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')
Example #18
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
Example #19
0
def _tests(makeKey=False, runGridlabD=True, showGDLABResults=False, cleanUp=True):
	'''Get and encrypt a .std/.seq files to a .json. cleanUp removes the unencrypted .glm and .json.
	'''
	# Inputs.
	user = "******"
	workDir = pJoin(os.getcwd())
	try: os.mkdir(pJoin(os.getcwd(),'encryptedFiles'))
	except: pass
	if makeKey:
		genKey(workDir, user)
		print "Made a new key for user:"******"Read key for user:"******"Working on:", stdString+",",seqString
			with open(pJoin("inFiles",stdString),'r') as stdFile, open(pJoin("inFiles",seqString),'r') as seqFile:
				stdContents, seqContents = stdFile.read(), seqFile.read()
			# print "First few lines before encryption:\n", stdContents[:100]
			encData = encryptData(stdContents, key)
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+stdString),"w+") as encFile:
				encFile.write(encData)
			encData = encryptData(seqContents, key)
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+seqString),"w+") as encFile:
				encFile.write(encData)
			# print "First few lines after enc:\n", encData[:100]
			# Read and decrypt to convert to a .glm.
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+stdString),'r') as inFile:
				encStdContents = inFile.read()
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+seqString),'r') as inFile2:
				encSeqContents = inFile2.read()
			print "\nCreated encrypted files:", "Encrypted_"+stdString+",", "Encrypted_"+seqString
			# Decrypt.
			decStdContents = decryptData(encStdContents,key)
			decSeqContents = decryptData(encSeqContents,key)
			# print "First few lines after dec:\n", decStdContents[:100]
			# Convert to .glm.
			def runMilConvert(stdContents, seqContents):
				myFeed, xScale, yScale = omf.milToGridlab.convert(stdContents,seqContents)
				with open(pJoin(workDir,stdString.replace('.std','.glm')),'w') as outFile:
					outFile.write(omf.feeder.sortedWrite(myFeed))
				myGraph = omf.feeder.treeToNxGraph(myFeed)
				omf.feeder.latLonNxGraph(myGraph, neatoLayout=False)
				plt.savefig(pJoin(workDir,stdString.replace('.std','.png')))
				plt.close()
			if not os.path.isfile(pJoin(workDir,stdString.replace('.std','.glm'))):
				runMilConvert(decStdContents, decSeqContents)
				print "Converted std/seq to glm."
			# Convert converted .glm to encrypted glm.
			with open(pJoin(workDir,stdString.replace('.std','.glm')),'r') as inGLM:
				glmContents = inGLM.read()
			encData = encryptData(glmContents, key)
			with open(pJoin(workDir, "encryptedFiles","Encrypted_"+stdString.replace('.std','.glm')),'w') as encFile:
				encFile.write(encData)
			print "Encrypted glm file:", stdString.replace('.std','.glm')
			# Decrypt .glm, convert to .json.
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+stdString.replace('.std','.glm')),'r') as encFile:
				encOutGlm = encFile.read()
			outGlm = decryptData(encOutGlm,key)
			newFeeder = gridlabImport(workDir, stdString.strip('.std'), outGlm)
			# Run gridlabD on decrypted GLM.
			if runGridlabD:
				output = gridlabd.runInFilesystem(newFeeder['tree'], attachments=testAttachments, keepFiles=False)
				if showGDLABResults:
					print "[STDERR]\n", (output['stderr'])
					print "[STDOUT]\n", (output['stdout'])
					print 'RAN GRIDLAB ON', stdString
			# Convert JSON to encrypted json.
			with open(pJoin(workDir,stdString.replace('.std','.json')),'r') as encFile:
				decJSON = encFile.read()
			encData = encryptData(decJSON, key)
			with open(pJoin(workDir,"encryptedFiles","Encrypted_"+stdString.replace('.std','.json')),'w') as encFile:
				encFile.write(encData)
			print "Encrypted JSON file:", stdString.replace('.std','.json')
			# Clean up unencrypted .glm and .json.
			if cleanUp:
				try:
					os.remove(pJoin(workDir,stdString.replace('.std','.glm')))
					print "Removed unencrypted file:", stdString.replace('.std','.glm')
				except: pass
				try:
					os.remove(pJoin(workDir,stdString.replace('.std','.json')))
					print "Removed unencrypted file:", stdString.replace('.std','.json')
				except: pass
		print "\nDone with encrypting all test files."
	except:
		print "Failed to encrypt", stdString, seqString
		exceptionCount += 1
		traceback.print_exc()
	return exceptionCount
Example #20
0
def runModel(modelDir, localTree, inData):
    '''This reads a glm file, changes the method of powerflow and reruns'''
    try:
        os.remove(pJoin(modelDir, "allOutputData.json"))
    except:
        pass
    allOutput = {}
    if not os.path.isdir(modelDir):
        os.makedirs(modelDir)
        inData["created"] = str(datetime.now())
    with open(pJoin(modelDir, "allInputData.json"), "w") as inputFile:
        json.dump(inData, inputFile, indent=4)
    binaryName = "gridlabd"
    for key in localTree:
        if "solver_method" in localTree[key].keys():
            print "current solver method", localTree[key]["solver_method"]
            localTree[key]["solver_method"] = 'FBS'
    #find the swing bus and recorder attached to substation
    for key in localTree:
        if localTree[key].get('bustype', '').lower() == 'swing':
            swingIndex = key
            swingName = localTree[key].get('name')
        if localTree[key].get('object',
                              '') == 'regulator' and localTree[key].get(
                                  'from', '') == swingName:
            regIndex = key
            regConfName = localTree[key]['configuration']
    #find the regulator and capacitor names and combine to form a string for volt-var control object
    regKeys = []
    accum_reg = ""
    for key in localTree:
        if localTree[key].get("object", "") == "regulator":
            accum_reg += localTree[key].get("name", "ERROR") + ","
            regKeys.append(key)
    regstr = accum_reg[:-1]
    print regKeys
    capKeys = []
    accum_cap = ""
    for key in localTree:
        if localTree[key].get("object", "") == "capacitor":
            accum_cap += localTree[key].get("name", "ERROR") + ","
            capKeys.append(key)
            if localTree[key].get("control", "").lower() == "manual":
                localTree[key]['control'] = "VOLT"
                print "changing capacitor control from manual to volt"
    capstr = accum_cap[:-1]
    print capKeys
    # 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': localTree[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': localTree[swingIndex]['name'],
        'property': 'voltage_A,voltage_B,voltage_C'
    }, {
        'object': 'recorder',
        'file': 'ZsubstationBottom.csv',
        'limit': '0',
        'parent': localTree[regIndex]['to'],
        'property': 'voltage_A,voltage_B,voltage_C'
    }]
    #recorder object for capacitor switching - if capacitors exist
    if capKeys != []:
        for key in capKeys:
            recorders.append({
                'object': 'recorder',
                'file': 'ZcapSwitch' + str(key) + '.csv',
                'limit': '0',
                'parent': localTree[key]['name'],
                'property': 'switchA,switchB,switchC'
            })
    #attach recorder process
    biggest = 1 + max([int(k) for k in localTree.keys()])
    for index, rec in enumerate(recorders):
        localTree[biggest + index] = rec
    #run a reference load flow
    HOURS = float(100)
    year_lp = False  #leap year
    feeder.adjustTime(localTree, HOURS, "hours", "2011-01-01")
    output = gridlabd.runInFilesystem(localTree,
                                      keepFiles=False,
                                      workDir=modelDir)
    os.remove(pJoin(modelDir, "PID.txt"))
    p = output['Zregulator.csv']['power_in.real']
    q = output['Zregulator.csv']['power_in.imag']
    #time delays from configuration files
    time_delay_reg = '30.0'
    time_delay_cap = '300.0'
    for key in localTree:
        if localTree[key].get('object', '') == "regulator_configuration":
            time_delay_reg = localTree[key]['time_delay']
            print "time_delay_reg", time_delay_reg
        # if localTree[key].get('object','') == "capacitor":
        # 	time_delay_cap = localTree[key]['time_delay']
        # 	print "time_delay_cap",time_delay_cap
    #change the recorder names
    for key in localTree:
        if localTree[key].get('object',
                              '') == "collector" or localTree[key].get(
                                  'object', '') == "recorder":
            if localTree[key].get('file', '').startswith('Z'):
                localTree[key]['file'] = localTree[key].get('file',
                                                            '').replace(
                                                                'Z', 'NewZ')
    #create volt-var control object
    max_key = max([int(key) for key in localTree.keys()])
    print max_key
    localTree[max_key + 1] = {
        'object': 'volt_var_control',
        'name': 'IVVC1',
        'control_method': 'ACTIVE',
        'capacitor_delay': str(time_delay_cap),
        'regulator_delay': str(time_delay_reg),
        'desired_pf': '0.99',
        'd_max': '0.6',
        'd_min': '0.1',
        'substation_link': str(localTree[regIndex]['name']),
        'regulator_list': regstr,
        'capacitor_list': capstr
    }
    #running powerflow analysis via gridalab after attaching a regulator
    feeder.adjustTime(localTree, HOURS, "hours", "2011-01-01")
    output1 = gridlabd.runInFilesystem(localTree,
                                       keepFiles=True,
                                       workDir=modelDir)
    os.remove(pJoin(modelDir, "PID.txt"))
    pnew = output1['NewZregulator.csv']['power_in.real']
    qnew = output1['NewZregulator.csv']['power_in.imag']
    #total real and imaginary losses as a function of time
    realLoss = []
    imagLoss = []
    realLossnew = []
    imagLossnew = []
    for element in range(int(HOURS)):
        r = 0.0
        i = 0.0
        rnew = 0.0
        inew = 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)'][element]
                i += output[device]['sum(power_losses_' + letter +
                                    '.imag)'][element]
                rnew += output1['New' + device]['sum(power_losses_' + letter +
                                                '.real)'][element]
                inew += output1['New' + device]['sum(power_losses_' + letter +
                                                '.imag)'][element]
        realLoss.append(r)
        imagLoss.append(i)
        realLossnew.append(rnew)
        imagLossnew.append(inew)
    #voltage calculations and tap calculations
    lowVoltage = []
    meanVoltage = []
    highVoltage = []
    lowVoltagenew = []
    meanVoltagenew = []
    highVoltagenew = []
    tap = {'A': [], 'B': [], 'C': []}
    tapnew = {'A': [], 'B': [], 'C': []}
    volt = {'A': [], 'B': [], 'C': []}
    voltnew = {'A': [], 'B': [], 'C': []}
    switch = {'A': [], 'B': [], 'C': []}
    switchnew = {'A': [], 'B': [], 'C': []}
    for element in range(int(HOURS)):
        for letter in ['A', 'B', 'C']:
            tap[letter].append(output['Zregulator.csv']['tap_' +
                                                        letter][element])
            tapnew[letter].append(
                output1['NewZregulator.csv']['tap_' + letter][element])
            #voltage real, imag
            vr, vi = sepRealImag(
                output['ZsubstationBottom.csv']['voltage_' + letter][element])
            volt[letter].append(math.sqrt(vr**2 + vi**2) / 60)
            vrnew, vinew = sepRealImag(
                output1['NewZsubstationBottom.csv']['voltage_' +
                                                    letter][element])
            voltnew[letter].append(math.sqrt(vrnew**2 + vinew**2) / 60)
            if capKeys != []:
                switch[letter].append(
                    output['ZcapSwitch' + str(int(capKeys[0])) +
                           '.csv']['switch' + letter][element])
                switchnew[letter].append(
                    output1['NewZcapSwitch' + str(int(capKeys[0])) +
                            '.csv']['switch' + letter][element])
        lowVoltage.append(
            float(output['ZvoltageJiggle.csv']['min(voltage_12.mag)'][element])
            / 2.0)
        meanVoltage.append(
            float(
                output['ZvoltageJiggle.csv']['mean(voltage_12.mag)'][element])
            / 2.0)
        highVoltage.append(
            float(output['ZvoltageJiggle.csv']['max(voltage_12.mag)'][element])
            / 2.0)
        lowVoltagenew.append(
            float(output1['NewZvoltageJiggle.csv']['min(voltage_12.mag)']
                  [element]) / 2.0)
        meanVoltagenew.append(
            float(output1['NewZvoltageJiggle.csv']['mean(voltage_12.mag)']
                  [element]) / 2.0)
        highVoltagenew.append(
            float(output1['NewZvoltageJiggle.csv']['max(voltage_12.mag)']
                  [element]) / 2.0)
    #energy calculations
    whEnergy = []
    whLosses = []
    whLoads = []
    whEnergy.append(sum(p) / 10**6)
    whLosses.append(sum(realLoss) / 10**6)
    whLoads.append((sum(p) - sum(realLoss)) / 10**6)
    whEnergy.append(sum(pnew) / 10**6)
    whLosses.append(sum(realLossnew) / 10**6)
    whLoads.append((sum(pnew) - sum(realLossnew)) / 10**6)
    indices = ['No IVVC', 'With IVVC']
    # energySalesRed = (whLoads[1]-whLoads[0])*(inData['wholesaleEnergyCostPerKwh'])*1000
    # lossSav = (whLosses[0]-whLosses[1])*inData['wholesaleEnergyCostPerKwh']*1000
    # print energySalesRed, lossSav
    #plots
    ticks = []
    plt.clf()
    plt.title("total energy")
    plt.ylabel("total load and losses (MWh)")
    for element in range(2):
        ticks.append(element)
        bar_loss = plt.bar(element, whLosses[element], 0.15, color='red')
        bar_load = plt.bar(element + 0.15,
                           whLoads[element],
                           0.15,
                           color='orange')
    plt.legend([bar_load[0], bar_loss[0]], ['total load', 'total losses'],
               bbox_to_anchor=(0., 0.915, 1., .102),
               loc=3,
               ncol=2,
               mode="expand",
               borderaxespad=0.1)
    plt.xticks([t + 0.15 for t in ticks], indices)
    plt.savefig(pJoin(modelDir, "total energy.png"))
    #real and imaginary power
    plt.figure("real power")
    plt.title("Real Power at substation")
    plt.ylabel("substation real power (MW)")
    pMW = [element / 10**6 for element in p]
    pMWn = [element / 10**6 for element in pnew]
    pw = plt.plot(pMW)
    npw = plt.plot(pMWn)
    plt.legend([pw[0], npw[0]], ['NO IVVC', 'WITH IVVC'],
               bbox_to_anchor=(0., 0.915, 1., .102),
               loc=3,
               ncol=2,
               mode="expand",
               borderaxespad=0.1)
    plt.savefig(pJoin(modelDir, "real power.png"))
    plt.figure("Reactive power")
    plt.title("Reactive Power at substation")
    plt.ylabel("substation reactive power (MVAR)")
    qMVAR = [element / 10**6 for element in q]
    qMVARn = [element / 10**6 for element in qnew]
    iw = plt.plot(qMVAR)
    niw = plt.plot(qMVARn)
    plt.legend([iw[0], niw[0]], ['NO IVVC', 'WITH IVVC'],
               bbox_to_anchor=(0., 0.915, 1., .102),
               loc=3,
               ncol=2,
               mode="expand",
               borderaxespad=0.1)
    plt.savefig(pJoin(modelDir, "imaginary power.png"))
    #voltage plots
    plt.figure("voltages as a function of time")
    f, ax = plt.subplots(2, sharex=True)
    f.suptitle("Voltages high and low")
    lv = ax[0].plot(lowVoltage, color='cadetblue')
    mv = ax[0].plot(meanVoltage, color='blue')
    hv = ax[0].plot(highVoltage, color='cadetblue')
    ax[0].legend([lv[0], mv[0], hv[0]],
                 ['low voltage', 'mean voltage', 'high voltage'],
                 bbox_to_anchor=(0., 0.915, 1., .1),
                 loc=3,
                 ncol=3,
                 mode="expand",
                 borderaxespad=0.1)
    ax[0].set_ylabel('NO IVVC')
    nlv = ax[1].plot(lowVoltagenew, color='cadetblue')
    nmv = ax[1].plot(meanVoltagenew, color='blue')
    nhv = ax[1].plot(highVoltagenew, color='cadetblue')
    ax[1].set_ylabel('WITH IVVC')
    plt.savefig(pJoin(modelDir, "Voltages.png"))
    #tap positions
    plt.figure("TAP positions NO IVVC")
    f, ax = plt.subplots(6, sharex=True)
    f.set_size_inches(18.5, 12.0)
    #f.suptitle("Regulator Tap positions")
    ax[0].plot(tap['A'])
    ax[0].set_title("Regulator Tap positions NO IVVC")
    ax[0].set_ylabel("TAP A")
    ax[1].plot(tap['B'])
    ax[1].set_ylabel("TAP B")
    ax[2].plot(tap['C'])
    ax[2].set_ylabel("TAP C")
    ax[3].plot(tapnew['A'])
    ax[3].set_title("WITH IVVC")
    ax[3].set_ylabel("TAP A")
    ax[4].plot(tapnew['B'])
    ax[4].set_ylabel("TAP B")
    ax[5].plot(tapnew['C'])
    ax[5].set_ylabel("TAP C")
    for subplot in range(6):
        ax[subplot].set_ylim(-20, 20)
    f.tight_layout()
    plt.savefig(pJoin(modelDir, "Regulator TAP positions.png"))
    #substation voltages
    plt.figure("substation voltage as a function of time")
    f, ax = plt.subplots(6, sharex=True)
    f.set_size_inches(18.5, 12.0)
    #f.suptitle("voltages at substation NO IVVC")
    ax[0].plot(volt['A'])
    ax[0].set_title('Substation voltages NO IVVC')
    ax[0].set_ylabel('voltage A')
    ax[1].plot(volt['B'])
    ax[1].set_ylabel('voltage B')
    ax[2].plot(volt['C'])
    ax[2].set_ylabel('voltage C')
    ax[3].plot(voltnew['A'])
    ax[3].set_title("WITH IVVC")
    ax[3].set_ylabel('voltage A')
    ax[4].plot(voltnew['B'])
    ax[4].set_ylabel('voltage B')
    ax[5].plot(voltnew['C'])
    ax[5].set_ylabel('voltage C')
    f.tight_layout()
    plt.savefig(pJoin(modelDir, "substation voltages.png"))
    #cap switches - plotted if capacitors are present
    if capKeys != []:
        plt.figure("capacitor switch state as a function of time")
        f, ax = plt.subplots(6, sharex=True)
        f.set_size_inches(18.5, 12.0)
        #f.suptitle("Capacitor switch state NO IVVC")
        ax[0].plot(switch['A'])
        ax[0].set_title("Capacitor switch state NO IVVC")
        ax[0].set_ylabel("switch A")
        ax[1].plot(switch['B'])
        ax[1].set_ylabel("switch B")
        ax[2].plot(switch['C'])
        ax[2].set_ylabel("switch C")
        ax[3].plot(switchnew['A'])
        ax[3].set_title("WITH IVVC")
        ax[3].set_ylabel("switch A")
        ax[4].plot(switchnew['B'])
        ax[4].set_ylabel("switch B")
        ax[5].plot(switchnew['C'])
        ax[5].set_ylabel("switch C")
        for subplot in range(6):
            ax[subplot].set_ylim(-2, 2)
        f.tight_layout()
        plt.savefig(pJoin(modelDir, "capacitor switch.png"))
    #plt.show()
    #monetization
    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'
    }
    if year_lp == True:
        febDays = 29
    else:
        febDays = 28
    monthHours = [
        int(31 * 24),
        int(febDays * 24),
        int(31 * 24),
        int(30 * 24),
        int(31 * 24),
        int(30 * 24),
        int(31 * 24),
        int(31 * 24),
        int(30 * 24),
        int(31 * 24),
        int(30 * 24),
        int(31 * 24)
    ]
    #find simulation months
    temp = 0
    cumulHours = []
    for x in range(12):
        temp += monthHours[x]
        cumulHours.append(temp)
    for i in range(12):
        if i == 0:
            lowval = 0
        else:
            lowval = cumulHours[i - 1]
        if HOURS <= cumulHours[i] and HOURS >= lowval:
            hourMonth = monthNames[i]
            hourIndex = i
    #calculate peaks for the number of months in simulation
    previndex = 0
    monthPeak = {}
    monthPeakNew = {}
    peakSaveDollars = {}
    energyLostDollars = {}
    lossRedDollars = {}
    for month in range(hourIndex + 1):
        index1 = int(previndex)
        index2 = int(min((index1 + int(monthHours[month])), HOURS))
        monthPeak[monthNames[month]] = max(p[index1:index2]) / 1000.0
        monthPeakNew[monthNames[month]] = max(pnew[index1:index2]) / 1000.0
        peakSaveDollars[monthNames[month]] = (
            monthPeak[monthNames[month]] - monthPeakNew[monthNames[month]]
        ) * inData['peakDemandCost' + str(monthToSeason[monthNames[month]]) +
                   'PerKw']
        lossRedDollars[
            monthNames[month]] = (sum(realLoss[index1:index2]) / 1000.0 -
                                  sum(realLossnew[index1:index2]) / 1000.0) * (
                                      inData['wholesaleEnergyCostPerKwh'])
        energyLostDollars[monthNames[month]] = (
            sum(p[index1:index2]) / 1000.0 - sum(pnew[index1:index2]) / 1000.0
            - sum(realLoss[index1:index2]) / 1000.0 +
            sum(realLossnew[index1:index2]) / 1000.0) * (
                inData['wholesaleEnergyCostPerKwh'] -
                inData['retailEnergyCostPerKwh'])
        previndex = index2
    #money charts
    simMonths = monthNames[:hourIndex + 1]
    fig = plt.figure("cost benefit barchart", figsize=(10, 8))
    ticks = range(len(simMonths))
    ticks1 = [element + 0.15 for element in ticks]
    ticks2 = [element + 0.30 for element in ticks]
    print ticks
    eld = [energyLostDollars[month] for month in simMonths]
    lrd = [lossRedDollars[month] for month in simMonths]
    psd = [peakSaveDollars[month] for month in simMonths]
    bar_eld = plt.bar(ticks, eld, 0.15, color='red')
    bar_psd = plt.bar(ticks1, psd, 0.15, color='blue')
    bar_lrd = plt.bar(ticks2, lrd, 0.15, color='green')
    plt.legend(
        [bar_eld[0], bar_psd[0], bar_lrd[0]],
        ['energyLostDollars', 'peakReductionDollars', 'lossReductionDollars'],
        bbox_to_anchor=(0., 1.015, 1., .102),
        loc=3,
        ncol=2,
        mode="expand",
        borderaxespad=0.1)
    monShort = [element[0:3] for element in simMonths]
    plt.xticks([t + 0.15 for t in ticks], monShort)
    plt.ylabel('Utility Savings ($)')
    plt.savefig(pJoin(modelDir, "spendChart.png"))
    with open(pJoin(modelDir, "spendChart.png"), "rb") as inFile:
        allOutput["spendChart"] = inFile.read().encode("base64")
    #cumulative savings graphs
    fig = plt.figure("cost benefit barchart", figsize=(10, 5))
    annualSavings = sum(eld) + sum(lrd) + sum(psd)
    annualSave = lambda x: (annualSavings - inData['omCost']) * x - inData[
        'capitalCost']
    simplePayback = inData['capitalCost'] / (annualSavings - inData['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"))
    with open(pJoin(modelDir, "savingsChart.png"), "rb") as inFile:
        allOutput["savingsChart"] = inFile.read().encode("base64")
    # Update the runTime in the input file.
    # endTime = datetime.now()
    # inDat["runTime"] = str(timedelta(seconds=int((endTime - startTime).total_seconds())))
    with open(pJoin(modelDir, "allInputData.json"), "w") as inFile:
        json.dump(inData, inFile, indent=4)
    with open(pJoin(modelDir, "allOutputData.json"), "w") as outFile:
        json.dump(allOutput, outFile, indent=4)
    print "DONE RUNNING", modelDir
Example #21
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')
	'parent':'solEngInverter', 
	'area':'30000 sf', 
	'generator_status':'ONLINE', 
	'object':'solar', 
	'efficiency':'0.14', 
	'panel_type':'SINGLE_CRYSTAL_SILICON' }
# myTree[oldMax + 7] = { 'interval':'3600',
# 	'parent':'solEngInverter',
# 	'limit':'0',
# 	'file':'Inverter_solEngInverter.csv',
# 	'property':'power_A,power_B,power_C',
# 	'object': 'recorder'}
feeder.adjustTime(myTree, 240, 'hours', '2014-01-01')

# Run here to test.
rawOut = runInFilesystem(myTree, attachments=myFeed['attachments'], keepFiles=True, workDir='.', glmName='Orville Tree Pond Calibrated.glm')

# # Show some output.
# print 'Output Keys:', rawOut.keys()
# plt.plot([abs(complex(x)) for x in rawOut['Inverter_solEngInverter.csv']['power_A']])
# plt.show()

# Write back the full feeder.
outJson = dict(myFeed)
with open('mspWeather.csv','r') as weatherFile:
	weatherString = weatherFile.read()
outJson['attachments']['mspWeather.csv'] = weatherString
outJson['tree'] = myTree
try: os.remove('./Orville Tree Pond Calibrated With Weather.json')
except: pass
with open('./Orville Tree Pond Calibrated With Weather.json', 'w') as outFile:
Example #23
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
Example #24
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)
Example #25
0
def _tests(makeKey=False, runGridlabD=True, showGDLABResults=False, cleanUp=True):
	'''Get and encrypt a .std/.seq files to a .json. cleanUp removes the unencrypted .glm and .json.
	'''
	# Inputs.
	user = "******"
	workDir = pJoin(os.getcwd())
	try: os.mkdir(pJoin(os.getcwd(),'encryptedFiles'))
	except: pass
	if makeKey:
		genKey(workDir, user)
		print "Made a new key for user:"******"Read key for user:"******"Working on:", stdString+",",seqString
			with open(pJoin("../../","uploads",stdString),'r') as stdFile, open(pJoin("../../","uploads",seqString),'r') as seqFile:
				stdContents, seqContents = stdFile.read(), seqFile.read()
			# print "First few lines before encryption:\n", stdContents[:100]
			encData = encryptData(stdContents, key)
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+stdString),"w+") as encFile:
				encFile.write(encData)
			encData = encryptData(seqContents, key)
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+seqString),"w+") as encFile:
				encFile.write(encData)
			# print "First few lines after enc:\n", encData[:100]
			# Read and decrypt to convert to a .glm.
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+stdString),'r') as inFile:
				encStdContents = inFile.read()
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+seqString),'r') as inFile2:
				encSeqContents = inFile2.read()
			print "\nCreated encrypted files:", "Encrypted_"+stdString+",", "Encrypted_"+seqString
			# Decrypt.
			decStdContents = decryptData(encStdContents,key)
			decSeqContents = decryptData(encSeqContents,key)
			# print "First few lines after dec:\n", decStdContents[:100]
			# Convert to .glm.
			def runMilConvert(stdContents, seqContents):
				myFeed, xScale, yScale = omf.milToGridlab.convert(stdContents,seqContents)
				with open(pJoin(workDir,stdString.replace('.std','.glm')),'w') as outFile:
					outFile.write(omf.feeder.sortedWrite(myFeed))
				myGraph = omf.feeder.treeToNxGraph(myFeed)
				omf.feeder.latLonNxGraph(myGraph, neatoLayout=False)
				plt.savefig(pJoin(workDir,stdString.replace('.std','.png')))
				plt.close()
			if not os.path.isfile(pJoin(workDir,stdString.replace('.std','.glm'))):
				runMilConvert(decStdContents, decSeqContents)
				print "Converted std/seq to glm."
			# Convert converted .glm to encrypted glm.
			with open(pJoin(workDir,stdString.replace('.std','.glm')),'r') as inGLM:
				glmContents = inGLM.read()
			encData = encryptData(glmContents, key)
			with open(pJoin(workDir, "encryptedFiles","Encrypted_"+stdString.replace('.std','.glm')),'w') as encFile:
				encFile.write(encData)
			print "Encrypted glm file:", stdString.replace('.std','.glm')
			# Decrypt .glm, convert to .json.
			with open(pJoin(workDir, "encryptedFiles", "Encrypted_"+stdString.replace('.std','.glm')),'r') as encFile:
				encOutGlm = encFile.read()
			outGlm = decryptData(encOutGlm,key)
			newFeeder = gridlabImport(workDir, stdString.strip('.std'), outGlm)
			# Run gridlabD on decrypted GLM.
			if runGridlabD:
				output = gridlabd.runInFilesystem(newFeeder['tree'], attachments=testAttachments, keepFiles=False)
				if showGDLABResults:
					print "[STDERR]\n", (output['stderr'])
					print "[STDOUT]\n", (output['stdout'])
					print 'RAN GRIDLAB ON', stdString
			# Convert JSON to encrypted json.
			with open(pJoin(workDir,stdString.replace('.std','.json')),'r') as encFile:
				decJSON = encFile.read()
			encData = encryptData(decJSON, key)
			with open(pJoin(workDir,"encryptedFiles","Encrypted_"+stdString.replace('.std','.json')),'w') as encFile:
				encFile.write(encData)
			print "Encrypted JSON file:", stdString.replace('.std','.json')
			# Clean up unencrypted .glm and .json.
			if cleanUp:
				try:
					os.remove(pJoin(workDir,stdString.replace('.std','.glm')))
					print "Removed unencrypted file:", stdString.replace('.std','.glm')
				except: pass
				try:
					os.remove(pJoin(workDir,stdString.replace('.std','.json')))
					print "Removed unencrypted file:", stdString.replace('.std','.json')
				except: pass
		print "\nDone with encrypting all test files."
	except:
		print "Failed to encrypt", stdString, seqString
		exceptionCount += 1
		traceback.print_exc()
	return exceptionCount
Example #26
0
    'object': 'solar',
    'efficiency': '0.14',
    'panel_type': 'SINGLE_CRYSTAL_SILICON'
}
# myTree[oldMax + 7] = { 'interval':'3600',
# 	'parent':'solEngInverter',
# 	'limit':'0',
# 	'file':'Inverter_solEngInverter.csv',
# 	'property':'power_A,power_B,power_C',
# 	'object': 'recorder'}
feeder.adjustTime(myTree, 240, 'hours', '2014-01-01')

# Run here to test.
rawOut = runInFilesystem(myTree,
                         attachments=myFeed['attachments'],
                         keepFiles=True,
                         workDir='.',
                         glmName='Orville Tree Pond Calibrated.glm')

# # Show some output.
# print 'Output Keys:', rawOut.keys()
# plt.plot([abs(complex(x)) for x in rawOut['Inverter_solEngInverter.csv']['power_A']])
# plt.show()

# Write back the full feeder.
outJson = dict(myFeed)
with open('mspWeather.csv', 'r') as weatherFile:
    weatherString = weatherFile.read()
outJson['attachments']['mspWeather.csv'] = weatherString
outJson['tree'] = myTree
try:
Example #27
0
def runForeground(modelDir,inData):
	'''This reads a glm file, changes the method of powerflow and reruns'''
	try:
		startTime = datetime.now()
		#calibrate and run cvrdynamic	
		feederPath = pJoin(__metaModel__._omfDir,"data", "Feeder", inData["feederName"].split("___")[0], inData["feederName"].split("___")[1]+'.json')
		scadaPath = pJoin(__metaModel__._omfDir,"uploads",(inData["scadaFile"]+'.tsv'))
		calibrate.omfCalibrate(modelDir,feederPath,scadaPath)
		allOutput = {}
		print "here"
		with open(pJoin(modelDir,"calibratedFeeder.json"), "r") as jsonIn:
			feederJson = json.load(jsonIn)
			localTree = feederJson.get("tree", {})
		for key in localTree:
			if "solver_method" in localTree[key].keys():
				print "current solver method", localTree[key]["solver_method"] 
				localTree[key]["solver_method"] = 'FBS'
		#find the swing bus and recorder attached to substation
		for key in localTree:
			if localTree[key].get('bustype','').lower() == 'swing':
				swingIndex = key
				swingName = localTree[key].get('name')
			if localTree[key].get('object','') == 'regulator' and localTree[key].get('from','') == swingName:
				regIndex = key
				regConfName = localTree[key]['configuration']
		#find the regulator and capacitor names and combine to form a string for volt-var control object
		regKeys = []
		accum_reg = ""
		for key in localTree:
			if localTree[key].get("object","") == "regulator":
				accum_reg += localTree[key].get("name","ERROR") + ","
				regKeys.append(key)
		regstr = accum_reg[:-1]
		print regKeys
		capKeys = []
		accum_cap = ""
		for key in localTree:
			if localTree[key].get("object","") == "capacitor":
				accum_cap += localTree[key].get("name","ERROR") + ","
				capKeys.append(key)
				if localTree[key].get("control","").lower() == "manual":
					localTree[key]['control'] = "VOLT"
					print "changing capacitor control from manual to volt"
		capstr = accum_cap[:-1]
		print capKeys
		# 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': localTree[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': localTree[swingIndex]['name'],
				'property': 'voltage_A,voltage_B,voltage_C'},
				{'object': 'recorder',
				'file': 'ZsubstationBottom.csv',
				'limit': '0',
				'parent': localTree[regIndex]['to'],
				'property': 'voltage_A,voltage_B,voltage_C'}]
		#recorder object for capacitor switching - if capacitors exist
		if capKeys != []:
			for key in capKeys:
				recorders.append({'object': 'recorder',
				'file': 'ZcapSwitch' + str(key) + '.csv',
				'limit': '0',
				'parent': localTree[key]['name'],
				'property': 'switchA,switchB,switchC'})
		#attach recorder process
		biggest = 1 + max([int(k) for k in localTree.keys()])
		for index, rec in enumerate(recorders):
			localTree[biggest + index] = rec
		#run a reference load flow
		HOURS = float(inData['simLengthHours'])
		simStartDate = inData['simStart']
		feeder.adjustTime(localTree,HOURS,"hours",simStartDate)	
		output = gridlabd.runInFilesystem(localTree,keepFiles=False,workDir=modelDir)
		os.remove(pJoin(modelDir,"PID.txt"))
		p = output['Zregulator.csv']['power_in.real']
		q = output['Zregulator.csv']['power_in.imag']
		#calculating length of simulation because it migth be different from the simulation input HOURS
		simRealLength = int(len(p))
		#time delays from configuration files
		time_delay_reg = '30.0'  
		time_delay_cap = '300.0'
		for key in localTree:
			if localTree[key].get('object','') == "regulator_configuration":
				time_delay_reg = localTree[key]['time_delay']
				print "time_delay_reg",time_delay_reg
			# if localTree[key].get('object','') == "capacitor":
			# 	time_delay_cap = localTree[key]['time_delay']
			# 	print "time_delay_cap",time_delay_cap
		#change the recorder names
		for key in localTree:
			if localTree[key].get('object','') == "collector" or localTree[key].get('object','') == "recorder":
				if localTree[key].get('file','').startswith('Z'):
					localTree[key]['file'] = localTree[key].get('file','').replace('Z','NewZ')
		#create volt-var control object
		max_key = max([int(key) for key in localTree.keys()])
		print max_key
		localTree[max_key+1] = {'object' : 'volt_var_control',
		'name' : 'IVVC1',
		'control_method' : 'ACTIVE',
		'capacitor_delay' : str(time_delay_cap),
		'regulator_delay' : str(time_delay_reg),
		'desired_pf' : '0.99',
		'd_max' : '0.6',
		'd_min' : '0.1',
		'substation_link' : str(localTree[regIndex]['name']),
		'regulator_list' : regstr,
		'capacitor_list': capstr} 
		#running powerflow analysis via gridalab after attaching a regulator
		feeder.adjustTime(localTree,HOURS,"hours",simStartDate)	
		output1 = gridlabd.runInFilesystem(localTree,keepFiles=True,workDir=modelDir)
		os.remove(pJoin(modelDir,"PID.txt"))
		pnew = output1['NewZregulator.csv']['power_in.real']
		qnew = output1['NewZregulator.csv']['power_in.imag']
		#total real and imaginary losses as a function of time
		def vecSum(u,v):
			''' Add vectors u and v element-wise. Return has len <= len(u) and <=len(v). '''
			return map(sum, zip(u,v))
		def zeroVec(length):
			''' Give a zero vector of input length. '''
			return [0 for x in xrange(length)]
		(realLoss, imagLoss, realLossnew, imagLossnew) = (zeroVec(int(HOURS)) for x in range(4))
		for device in ['ZlossesOverhead.csv','ZlossesTransformer.csv','ZlossesUnderground.csv']:
			for letter in ['A','B','C']:
				realLoss = vecSum(realLoss, output[device]['sum(power_losses_' + letter + '.real)'])
				imagLoss = vecSum(imagLoss, output[device]['sum(power_losses_' + letter + '.imag)'])
				realLossnew = vecSum(realLossnew, output1['New'+device]['sum(power_losses_' + letter + '.real)'])
				imagLossnew = vecSum(imagLossnew, output1['New'+device]['sum(power_losses_' + letter + '.imag)'])
		#voltage calculations and tap calculations
		def divby2(u):
			'''divides by 2'''
			return u/2
		lowVoltage = []
		meanVoltage = []
		highVoltage = []
		lowVoltagenew = []
		meanVoltagenew = []
		highVoltagenew = []
		tap = {'A':[],'B':[],'C':[]}
		tapnew = {'A':[],'B':[],'C':[]}
		volt = {'A':[],'B':[],'C':[]}
		voltnew = {'A':[],'B':[],'C':[]}
		switch = {'A':[],'B':[],'C':[]}
		switchnew = {'A':[],'B':[],'C':[]}
		for letter in ['A','B','C']:
			tap[letter] = output['Zregulator.csv']['tap_' + letter]
			tapnew[letter] = output1['NewZregulator.csv']['tap_' + letter]
			if capKeys != []:
				switch[letter] = output['ZcapSwitch' + str(int(capKeys[0])) + '.csv']['switch'+ letter]
				switchnew[letter] = output1['NewZcapSwitch' + str(int(capKeys[0])) + '.csv']['switch'+ letter]
			volt[letter] = map(returnMag,output['ZsubstationBottom.csv']['voltage_'+letter])
			voltnew[letter] = map(returnMag,output1['NewZsubstationBottom.csv']['voltage_'+letter])
		lowVoltage = map(divby2,output['ZvoltageJiggle.csv']['min(voltage_12.mag)'])
		lowVoltagenew = map(divby2,output1['NewZvoltageJiggle.csv']['min(voltage_12.mag)'])
		meanVoltage = map(divby2,output['ZvoltageJiggle.csv']['mean(voltage_12.mag)'])
		meanVoltagenew = map(divby2,output1['NewZvoltageJiggle.csv']['mean(voltage_12.mag)'])
		highVoltage = map(divby2,output['ZvoltageJiggle.csv']['max(voltage_12.mag)'])
		highVoltagenew = map(divby2,output1['NewZvoltageJiggle.csv']['max(voltage_12.mag)'])
		#energy calculations
		whEnergy = []
		whLosses = []
		whLoads = []
		whEnergy.append(sum(p)/10**6)
		whLosses.append(sum(realLoss)/10**6)
		whLoads.append((sum(p)-sum(realLoss))/10**6)
		whEnergy.append(sum(pnew)/10**6)
		whLosses.append(sum(realLossnew)/10**6)
		whLoads.append((sum(pnew)-sum(realLossnew))/10**6)
		indices = ['No IVVC', 'With IVVC']
		# energySalesRed = (whLoads[1]-whLoads[0])*(inData['wholesaleEnergyCostPerKwh'])*1000
		# lossSav = (whLosses[0]-whLosses[1])*inData['wholesaleEnergyCostPerKwh']*1000
		# print energySalesRed, lossSav
		#plots
		ticks = []
		plt.clf()
		plt.title("total energy")
		plt.ylabel("total load and losses (MWh)")
		for element in range(2):
			ticks.append(element)
			bar_loss = plt.bar(element, whLosses[element], 0.15, color= 'red')
			bar_load = plt.bar(element+0.15, whLoads[element], 0.15, color= 'orange')
		plt.legend([bar_load[0],bar_loss[0]],['total load', 'total losses'],bbox_to_anchor=(0., 0.915, 1., .102), loc=3,
			       ncol=2, mode="expand", borderaxespad=0.1)
		plt.xticks([t+0.15 for t in ticks],indices)
		plt.savefig(pJoin(modelDir,"totalEnergy.png"))
		#real and imaginary power
		plt.figure("real power")
		plt.title("Real Power at substation")
		plt.ylabel("substation real power (MW)")
		pMW = [element/10**6 for element in p]
		pMWn = [element/10**6 for element in pnew]
		pw = plt.plot(pMW)
		npw = plt.plot(pMWn)
		plt.legend([pw[0], npw[0]], ['NO IVVC','WITH IVVC'],bbox_to_anchor=(0., 0.915, 1., .102), loc=3,
			ncol=2, mode="expand", borderaxespad=0.1)
		plt.savefig(pJoin(modelDir,"realPower.png"))
		plt.figure("Reactive power")
		plt.title("Reactive Power at substation")
		plt.ylabel("substation reactive power (MVAR)")
		qMVAR = [element/10**6 for element in q]
		qMVARn = [element/10**6 for element in qnew]
		iw = plt.plot(qMVAR)
		niw = plt.plot(qMVARn)
		plt.legend([iw[0], niw[0]], ['NO IVVC','WITH IVVC'],bbox_to_anchor=(0., 0.915, 1., .102), loc=3,
			ncol=2, mode="expand", borderaxespad=0.1)
		plt.savefig(pJoin(modelDir,"imaginaryPower.png"))
		#voltage plots
		plt.figure("voltages as a function of time")
		f,ax = plt.subplots(2,sharex=True)
		f.suptitle("Min and Max voltages on the feeder")
		lv = ax[0].plot(lowVoltage,color = 'cadetblue')
		mv = ax[0].plot(meanVoltage,color = 'blue')
		hv = ax[0].plot(highVoltage, color = 'cadetblue')
		ax[0].legend([lv[0], mv[0], hv[0]], ['low voltage','mean voltage','high voltage'],bbox_to_anchor=(0., 0.915, 1., .1), loc=3,
			ncol=3, mode="expand", borderaxespad=0.1)
		ax[0].set_ylabel('NO IVVC')
		nlv = ax[1].plot(lowVoltagenew,color = 'cadetblue')
		nmv = ax[1].plot(meanVoltagenew,color = 'blue')
		nhv = ax[1].plot(highVoltagenew, color = 'cadetblue')
		ax[1].set_ylabel('WITH IVVC')
		plt.savefig(pJoin(modelDir,"Voltages.png"))
		#tap positions
		plt.figure("TAP positions NO IVVC")
		f,ax = plt.subplots(6,sharex=True)
		f.set_size_inches(10,12.0)
		#f.suptitle("Regulator Tap positions")
		ax[0].plot(tap['A'])
		ax[0].set_title("Regulator Tap positions NO IVVC")
		ax[0].set_ylabel("TAP A")
		ax[1].plot(tap['B'])
		ax[1].set_ylabel("TAP B")
		ax[2].plot(tap['C'])
		ax[2].set_ylabel("TAP C")
		ax[3].plot(tapnew['A'])
		ax[3].set_title("WITH IVVC")
		ax[3].set_ylabel("TAP A")
		ax[4].plot(tapnew['B'])
		ax[4].set_ylabel("TAP B")
		ax[5].plot(tapnew['C'])
		ax[5].set_ylabel("TAP C")
		for subplot in range(6):
			ax[subplot].set_ylim(-20,20)
		f.tight_layout()
		plt.savefig(pJoin(modelDir,"RegulatorTAPpositions.png"))
		#substation voltages
		plt.figure("substation voltage as a function of time")
		f,ax = plt.subplots(6,sharex=True)
		f.set_size_inches(10,12.0)
		#f.suptitle("voltages at substation NO IVVC")
		ax[0].plot(volt['A'])
		ax[0].set_title('Substation voltages NO IVVC')
		ax[0].set_ylabel('voltage A')
		ax[1].plot(volt['B'])
		ax[1].set_ylabel('voltage B')
		ax[2].plot(volt['C'])
		ax[2].set_ylabel('voltage C')
		ax[3].plot(voltnew['A'])
		ax[3].set_title("WITH IVVC")
		ax[3].set_ylabel('voltage A')
		ax[4].plot(voltnew['B'])
		ax[4].set_ylabel('voltage B')
		ax[5].plot(voltnew['C'])
		ax[5].set_ylabel('voltage C')
		f.tight_layout()
		plt.savefig(pJoin(modelDir,"substationVoltages.png"))
		#cap switches
		plt.figure("capacitor switch state as a function of time")
		f,ax = plt.subplots(6,sharex=True)
		f.set_size_inches(10,12.0)
		#f.suptitle("Capacitor switch state NO IVVC")
		ax[0].plot(switch['A'])
		ax[0].set_title("Capacitor switch state NO IVVC")
		ax[0].set_ylabel("switch A")
		ax[1].plot(switch['B'])
		ax[1].set_ylabel("switch B")
		ax[2].plot(switch['C'])
		ax[2].set_ylabel("switch C")
		ax[3].plot(switchnew['A'])
		ax[3].set_title("WITH IVVC")
		ax[3].set_ylabel("switch A")
		ax[4].plot(switchnew['B'])
		ax[4].set_ylabel("switch B")
		ax[5].plot(switchnew['C'])
		ax[5].set_ylabel("switch C")
		for subplot in range(6):
			ax[subplot].set_ylim(-2,2)
		f.tight_layout()
		plt.savefig(pJoin(modelDir,"capacitorSwitch.png"))
		#plt.show()
		#monetization
		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'}
		#calculate the month and hour of simulation start and month and hour of simulation end
		simStartTimestamp = simStartDate + " 00:00:00"
		simFormattedDate = datetime.strptime(simStartTimestamp,"%Y-%m-%d %H:%M:%S")
		simStartMonthNum = int(simFormattedDate.strftime('%m'))
		simstartMonth = monthNames[simStartMonthNum-1]
		simStartDay = int(simFormattedDate.strftime('%d'))
		if calendar.isleap(int(simFormattedDate.strftime('%Y'))):
			febDays = 29
		else:
			febDays = 28
		monthHours = [int(31*24),int(febDays*24),int(31*24),int(30*24),int(31*24),int(30*24),int(31*24),int(31*24),int(30*24),int(31*24),int(30*24),int(31*24)]
		simStartIndex = int(sum(monthHours[:(simStartMonthNum-1)])+(simStartDay-1)*24)
		temp = 0
		cumulHours = [0]
		for x in range(12):
			temp += monthHours[x]
			cumulHours.append(temp)
		for i in range((simStartMonthNum),13):
			if int(simStartIndex+simRealLength)<=cumulHours[i] and int(simStartIndex+simRealLength)>cumulHours[i-1]:
				simEndMonthNum = i-1
				simEndMonth = monthNames[simEndMonthNum]
		print simstartMonth,simEndMonth
		#calculate peaks for the number of months in simulation
		previndex = 0
		monthPeak = {}
		monthPeakNew = {}
		peakSaveDollars = {}
		energyLostDollars = {}
		lossRedDollars = {}
		simMonthList = monthNames[monthNames.index(simstartMonth):(monthNames.index(simEndMonth)+1)] 
		print simMonthList
		for monthElement in simMonthList:
			print monthElement
			month = monthNames.index(monthElement)
			index1 = int(previndex)
			index2 = int(min((index1 + int(monthHours[month])), simRealLength))
			monthPeak[monthElement] = max(p[index1:index2])/1000.0
			monthPeakNew[monthElement] = max(pnew[index1:index2])/1000.0
			peakSaveDollars[monthElement] = (monthPeak[monthElement]-monthPeakNew[monthElement])*float(inData['peakDemandCost'+str(monthToSeason[monthElement])+'PerKw'])
			lossRedDollars[monthElement] = (sum(realLoss[index1:index2])/1000.0 - sum(realLossnew[index1:index2])/1000.0)*(float(inData['wholesaleEnergyCostPerKwh']))
			energyLostDollars[monthElement] = (sum(p[index1:index2])/1000.0  - sum(pnew[index1:index2])/1000.0  - sum(realLoss[index1:index2])/1000.0  
				+ sum(realLossnew[index1:index2])/1000.0 )*(float(inData['wholesaleEnergyCostPerKwh']) - float(inData['retailEnergyCostPerKwh']))
			previndex = index2
		#money charts
		fig = plt.figure("cost benefit barchart",figsize=(10,8))
		ticks = range(len(simMonthList))
		ticks1 = [element+0.15 for element in ticks]
		ticks2 = [element+0.30 for element in ticks]
		print ticks
		eld = [energyLostDollars[month] for month in simMonthList]
		lrd = [lossRedDollars[month] for month in simMonthList]
		psd = [peakSaveDollars[month] for month in simMonthList]
		bar_eld = plt.bar(ticks,eld,0.15,color='red') 
		bar_psd = plt.bar(ticks1,psd,0.15,color='blue')
		bar_lrd = plt.bar(ticks2,lrd,0.15,color='green')
		plt.legend([bar_eld[0], bar_psd[0], bar_lrd[0]], ['energyLostDollars','peakReductionDollars','lossReductionDollars'],bbox_to_anchor=(0., 1.015, 1., .102), loc=3,
			ncol=2, mode="expand", borderaxespad=0.1)
		monShort = [element[0:3] for element in simMonthList]
		plt.xticks([t+0.15 for t in ticks],monShort)
		plt.ylabel('Utility Savings ($)')
		plt.savefig(pJoin(modelDir,"spendChart.png"))
		#cumulative savings graphs
		fig = plt.figure("cost benefit barchart",figsize=(10,5))
		annualSavings = sum(eld) + sum(lrd) + sum(psd)
		annualSave = lambda x:(annualSavings - float(inData['omCost'])) * x - float(inData['capitalCost'])
		simplePayback = float(inData['capitalCost'])/(annualSavings - float(inData['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"))
		#get exact time stamps from the CSV files generated by Gridlab-D
		timeWithZone =  output['Zregulator.csv']['# timestamp']
		timestamps = [element[:19] for element in timeWithZone]
		#data for highcharts
		allOutput["timeStamps"] = timestamps
		allOutput["noCVRPower"] = p
		allOutput["withCVRPower"] = pnew
		allOutput["noCVRLoad"] = whLoads[0]
		allOutput["withCVRLoad"] = whLoads[1]
		allOutput["noCVRLosses"] = whLosses[0]
		allOutput["withCVRLosses"] = whLosses[1]
		allOutput["noCVRTaps"] = tap
		allOutput["withCVRTaps"] = tapnew
		allOutput["noCVRSubVolts"] = volt
		allOutput["withCVRSubVolts"] = voltnew
		allOutput["noCVRCapSwitch"] = switch
		allOutput["withCVRCapSwitch"] = switchnew
		allOutput["noCVRHighVolt"] = highVoltage
		allOutput["withCVRHighVolt"] = highVoltagenew
		allOutput["noCVRLowVolt"] = lowVoltage
		allOutput["withCVRLowVolt"] = lowVoltagenew
		allOutput["noCVRMeanVolt"] = meanVoltage
		allOutput["withCVRMeanVolt"] = meanVoltagenew
		#monetization
		allOutput["simMonthList"] = monShort
		allOutput["energyLostDollars"] = energyLostDollars
		allOutput["lossRedDollars"] = lossRedDollars
		allOutput["peakSaveDollars"] = peakSaveDollars
		allOutput["annualSave"] = [annualSave(x) for x in range(31)]
		# Update the runTime in the input file.
		endTime = datetime.now()
		inData["runTime"] = str(timedelta(seconds=int((endTime - startTime).total_seconds())))
		with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
			json.dump(inData, inFile, indent=4)
		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:
		print "Oops, Model Crashed!!!" 
		cancel(modelDir)
		print e
Example #28
0
def comparesol(modelDir,localTree):
	'''This reads a glm file, changes the method of powerflow and reruns'''
	print "Testing GridlabD solver."

	startTime = datetime.now()

	binaryName = "gridlabd"

	for key in localTree:
		if "solver_method" in localTree[key].keys():
			solvmeth = localTree[key]["solver_method"]
			print "success", solvmeth 
			if solvmeth == 'NR':
				localTree[key]["solver_method"] = 'FBS'
			else:
				localTree[key]["solver_method"] = 'NR'

	# feeder.attachRecorders(localTree, "Regulator", "object", "regulator")
	# feeder.attachRecorders(localTree, "CollectorVoltage", None, None)	

	# last_key = len(localTree)

	# print last_key



	for key in localTree:
		if localTree[key].get('bustype','').lower() == 'swing':
			swingIndex = key
			swingName = localTree[key].get('name')

	print swingIndex, swingName

	for key in localTree:
		if localTree[key].get('object','') == 'regulator' and localTree[key].get('from','') == swingName:
			regIndex = key
			regConfName = localTree[key]['configuration']

	print regIndex


	# 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': localTree[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': localTree[swingIndex]['name'],
			'property': 'voltage_A,voltage_B,voltage_C'},
			{'object': 'recorder',
			'file': 'ZsubstationBottom.csv',
			'limit': '0',
			'parent': localTree[regIndex]['to'],
			'property': 'voltage_A,voltage_B,voltage_C'} ]
	
	biggest = 1 + max([int(k) for k in localTree.keys()])
	for index, rec in enumerate(recorders):
		localTree[biggest + index] = rec


	max_key = max([int(key) for key in localTree.keys()])
	print max_key

	regKeys = []
	accum = ""

	for key in localTree:
		if localTree[key].get("object","") == "regulator":
			accum += localTree[key].get("name","ERROR") + ","
			regKeys.append(key)

	regstr = accum[:-1]

	print regKeys
	print regstr, type(regstr)

	localTree[max_key+1] = {'object' : 'volt_var_control',
	'name' : 'volt_var_control',
	'control_method' : 'ACTIVE',
	'capacitor_delay' : '30.0',
	'regulator_delay' : '30.0',
	'desired_pf' : '0.99',
	'd_max' : '0.6',
	'd_min' : '0.1',
	'substation_link' : 'substation_transformer',
	'regulator_list' : regstr } 


	feeder.adjustTime(tree=localTree, simLength=float("8760"),
			simLengthUnits="hours", simStartDate="2012-01-01")	

	output = gridlabd.runInFilesystem(localTree,keepFiles=True,workDir=modelDir)
	os.remove(pJoin(modelDir,"PID.txt"))
	

	p = output['Zregulator.csv']['power_in.real']
	q = output['Zregulator.csv']['power_in.imag']

	xtime = {}

	for key in output:
		if '# timestamp' in output[key]:
			xtime['timeStamps'] = output[key]['# timestamp']

	#print type(xtime['timeStamps'][0])
	#print len(p)

	#xaxtick = str(xtime['timeStamps'])

	# plt.plot(range(8760),p)
	# plt.show()

	# print "p=" , p
	# print "q=" , q
	print "DONE RUNNING", modelDir
Example #29
0
def comparesol(modelDir, localTree):
    '''This reads a glm file, changes the method of powerflow and reruns'''
    print "Testing GridlabD solver."

    startTime = datetime.now()

    binaryName = "gridlabd"

    for key in localTree:
        if "solver_method" in localTree[key].keys():
            solvmeth = localTree[key]["solver_method"]
            print "success", solvmeth
            if solvmeth == 'NR':
                localTree[key]["solver_method"] = 'FBS'
            else:
                localTree[key]["solver_method"] = 'NR'

    # feeder.attachRecorders(localTree, "Regulator", "object", "regulator")
    # feeder.attachRecorders(localTree, "CollectorVoltage", None, None)

    # last_key = len(localTree)

    # print last_key

    for key in localTree:
        if localTree[key].get('bustype', '').lower() == 'swing':
            swingIndex = key
            swingName = localTree[key].get('name')

    print swingIndex, swingName

    for key in localTree:
        if localTree[key].get('object',
                              '') == 'regulator' and localTree[key].get(
                                  'from', '') == swingName:
            regIndex = key
            regConfName = localTree[key]['configuration']

    print regIndex

    # 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': localTree[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': localTree[swingIndex]['name'],
        'property': 'voltage_A,voltage_B,voltage_C'
    }, {
        'object': 'recorder',
        'file': 'ZsubstationBottom.csv',
        'limit': '0',
        'parent': localTree[regIndex]['to'],
        'property': 'voltage_A,voltage_B,voltage_C'
    }]

    biggest = 1 + max([int(k) for k in localTree.keys()])
    for index, rec in enumerate(recorders):
        localTree[biggest + index] = rec

    max_key = max([int(key) for key in localTree.keys()])
    print max_key

    regKeys = []
    accum = ""

    for key in localTree:
        if localTree[key].get("object", "") == "regulator":
            accum += localTree[key].get("name", "ERROR") + ","
            regKeys.append(key)

    regstr = accum[:-1]

    print regKeys
    print regstr, type(regstr)

    localTree[max_key + 1] = {
        'object': 'volt_var_control',
        'name': 'volt_var_control',
        'control_method': 'ACTIVE',
        'capacitor_delay': '30.0',
        'regulator_delay': '30.0',
        'desired_pf': '0.99',
        'd_max': '0.6',
        'd_min': '0.1',
        'substation_link': 'substation_transformer',
        'regulator_list': regstr
    }

    feeder.adjustTime(tree=localTree,
                      simLength=float("8760"),
                      simLengthUnits="hours",
                      simStartDate="2012-01-01")

    output = gridlabd.runInFilesystem(localTree,
                                      keepFiles=True,
                                      workDir=modelDir)
    os.remove(pJoin(modelDir, "PID.txt"))

    p = output['Zregulator.csv']['power_in.real']
    q = output['Zregulator.csv']['power_in.imag']

    xtime = {}

    for key in output:
        if '# timestamp' in output[key]:
            xtime['timeStamps'] = output[key]['# timestamp']

    #print type(xtime['timeStamps'][0])
    #print len(p)

    #xaxtick = str(xtime['timeStamps'])

    # plt.plot(range(8760),p)
    # plt.show()

    # print "p=" , p
    # print "q=" , q
    print "DONE RUNNING", modelDir
Example #30
0
def omfCalibrate(workDir, feederPath, scadaPath):
    '''calibrates a feeder and saves the calibrated tree at a location'''
    with open(feederPath, "r") as jsonIn:
        feederJson = json.load(jsonIn)
        tree = feederJson.get("tree", {})
    scadaSubPower = _processScadaData(workDir, scadaPath)
    # Force FBS powerflow, because NR fails a lot.
    for key in tree:
        if tree[key].get("module", "").lower() == "powerflow":
            tree[key] = {"module": "powerflow", "solver_method": "FBS"}
    # Attach player.
    classOb = {
        "class": "player",
        "variable_names": ["value"],
        "variable_types": ["double"]
    }
    playerOb = {
        "object": "player",
        "property": "value",
        "name": "scadaLoads",
        "file": "subScada.player",
        "loop": "0"
    }
    maxKey = feeder.getMaxKey(tree)
    tree[maxKey + 1] = classOb
    tree[maxKey + 2] = playerOb
    # Make loads reference player.
    loadTemplate = {
        "object": "triplex_load",
        "power_pf_12": "0.95",
        "impedance_pf_12": "0.98",
        "power_pf_12": "0.90",
        "impedance_fraction_12": "0.7",
        "power_fraction_12": "0.3"
    }
    for key in tree:
        ob = tree[key]
        if ob.get("object",
                  "") == "triplex_node" and ob.get("power_12", "") != "":
            newOb = dict(loadTemplate)
            newOb["name"] = ob.get("name", "")
            newOb["parent"] = ob.get("parent", "")
            newOb["phases"] = ob.get("phases", "")
            newOb["nominal_voltage"] = ob.get("nominal_voltage", "")
            newOb["latitude"] = ob.get("latitude", "0")
            newOb["longitude"] = ob.get("longitude", "0")
            oldPow = ob.get("power_12", "").replace("j", "d")
            pythagPower = gridlabd._strClean(oldPow)
            newOb["base_power_12"] = "scadaLoads.value*" + str(pythagPower)
            tree[key] = newOb
    # Search for the substation regulator and attach a recorder there.
    for key in tree:
        if tree[key].get('bustype', '').lower() == 'swing':
            swingName = tree[key].get('name')
    for key in tree:
        if tree[key].get('object', '') == 'regulator' and tree[key].get(
                'from', '') == swingName:
            regIndex = key
            SUB_REG_NAME = tree[key]['name']
    recOb = {
        "object": "recorder",
        "parent": SUB_REG_NAME,
        "property": "power_in.real,power_in.imag",
        "file": "caliSub.csv",
        "interval": "900"
    }
    tree[maxKey + 3] = recOb
    HOURS = 100
    feeder.adjustTime(tree, HOURS, "hours", "2011-01-01")
    # Run Gridlabd.
    output = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=workDir)
    # Calculate scaling constant.
    outRealPow = output["caliSub.csv"]["power_in.real"]
    outImagPower = output["caliSub.csv"]["power_in.imag"]
    outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5 / 1000
                     for x in zip(outRealPow, outImagPower)]
    # HACK: ignore first time step in output and input because GLD sometimes breaks the first step.
    SCAL_CONST = sum(scadaSubPower[1:HOURS]) / sum(outAppPowerKw[1:HOURS])
    # Rewrite the subScada.player file so all the power values are multiplied by the SCAL_CONSTANT.
    newPlayData = []
    with open(pJoin(workDir, "subScada.player"), "r") as playerFile:
        for line in playerFile:
            (key, val) = line.split(',')
            newPlayData.append(
                str(key) + ',' + str(float(val) * SCAL_CONST) + "\n")
    with open(pJoin(workDir, "subScadaCalibrated.player"), "w") as playerFile:
        for row in newPlayData:
            playerFile.write(row)
    # Test by running a glm with subScadaCalibrated.player and caliSub.csv2.
    tree[maxKey + 2]["file"] = "subScadaCalibrated.player"
    tree[maxKey + 3]["file"] = "caliSubCheck.csv"
    secondOutput = gridlabd.runInFilesystem(tree,
                                            keepFiles=True,
                                            workDir=workDir)
    plt.plot(outAppPowerKw[1:HOURS], label="initialGuess")
    plt.plot(scadaSubPower[1:HOURS], label="scadaSubPower")
    secondAppKw = [
        (x[0]**2 + x[1]**2)**0.5 / 1000
        for x in zip(secondOutput["caliSubCheck.csv"]["power_in.real"],
                     secondOutput["caliSubCheck.csv"]["power_in.imag"])
    ]
    plt.plot(secondAppKw[1:HOURS], label="finalGuess")
    plt.legend(loc=3)
    plt.savefig(pJoin(workDir, "caliCheckPlot.png"))
    # Write the final output.
    with open(pJoin(workDir, "calibratedFeeder.json"), "w") as outJson:
        playerString = open(pJoin(workDir, "subScadaCalibrated.player")).read()
        feederJson["attachments"]["subScadaCalibrated.player"] = playerString
        feederJson["tree"] = tree
        json.dump(feederJson, outJson, indent=4)
    return
Example #31
0
 def runPowerflowIter(tree, scadaSubPower):
     '''Runs powerflow once, then iterates.'''
     # Run initial powerflow to get power.
     print "Starting calibration."
     print "Goal of calibration: Error: %s, Iterations: <%s, trim: %s" % (
         calibrateError[0], calibrateError[1], trim)
     output = gridlabd.runInFilesystem(tree,
                                       keepFiles=True,
                                       workDir=pJoin(workDir, "gridlabD"))
     outRealPow = output["caliSub.csv"]["measured_real_power"][
         trim:simLength]
     outImagPower = output["caliSub.csv"]["measured_reactive_power"][
         trim:simLength]
     outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5 / 1000
                      for x in zip(outRealPow, outImagPower)]
     lastFile = "subScada.player"
     nextFile = "subScadaCalibrated.player"
     nextPower = outAppPowerKw
     error = (sum(outRealPow) / 1000 -
              sum(scadaSubPower)) / sum(scadaSubPower)
     iteration = 1
     print "First error:", error
     while abs(error) > calibrateError[0] and iteration < calibrateError[1]:
         # Run calibration and iterate up to 5 times.
         SCAL_CONST = sum(scadaSubPower) / sum(nextPower)
         print "Calibrating & running again... Error: %s, Iteration: %s, SCAL_CONST: %s" % (
             str(round(abs(error * 100),
                       6)), str(iteration), round(SCAL_CONST, 6))
         newPlayData = []
         with open(pJoin(pJoin(workDir, "gridlabD"), lastFile),
                   "r") as playerFile:
             for line in playerFile:
                 (key, val) = line.split(',')
                 newPlayData.append(
                     str(key) + ',' + str(float(val) * SCAL_CONST) + "\n")
         with open(pJoin(pJoin(workDir, "gridlabD"), nextFile),
                   "w") as playerFile:
             for row in newPlayData:
                 playerFile.write(row)
         tree[playerKey]["file"] = nextFile
         tree[outputRecorderKey]["file"] = "caliSubCheck.csv"
         nextOutput = gridlabd.runInFilesystem(tree,
                                               keepFiles=True,
                                               workDir=pJoin(
                                                   workDir, "gridlabD"))
         outRealPowIter = nextOutput["caliSubCheck.csv"][
             "measured_real_power"][trim:simLength]
         outImagPowerIter = nextOutput["caliSubCheck.csv"][
             "measured_reactive_power"][trim:simLength]
         nextAppKw = [(x[0]**2 + x[1]**2)**0.5 / 1000
                      for x in zip(outRealPowIter, outImagPowerIter)]
         lastFile = nextFile
         nextFile = "subScadaCalibrated" + str(iteration) + ".player"
         nextPower = nextAppKw
         # Compute error and iterate.
         error = (sum(outRealPowIter) / 1000 -
                  sum(scadaSubPower)) / sum(scadaSubPower)
         iteration += 1
     else:
         if iteration == 1: outRealPowIter = outRealPow
         SCAL_CONST = 1.0
     print "Calibration done: Error: %s, Iteration: %s, SCAL_CONST: %s" % (
         str(round(abs(error * 100),
                   2)), str(iteration), round(SCAL_CONST, 2))
     return outRealPow, outRealPowIter, lastFile, iteration
Example #32
0
def omfCalibrate(workDir, feederPath, scadaPath):
	'''calibrates a feeder and saves the calibrated tree at a location'''
	with open(feederPath, "r") as jsonIn:
		feederJson = json.load(jsonIn)
		tree = feederJson.get("tree", {})
	scadaSubPower = _processScadaData(workDir,scadaPath)
	# Force FBS powerflow, because NR fails a lot.
	for key in tree:
		if tree[key].get("module","").lower() == "powerflow":
			tree[key] = {"module":"powerflow","solver_method":"FBS"}
	# Attach player.
	classOb = {"class":"player", "variable_names":["value"], "variable_types":["double"]}
	playerOb = {"object":"player", "property":"value", "name":"scadaLoads", "file":"subScada.player", "loop":"0"}
	maxKey = feeder.getMaxKey(tree)
	tree[maxKey+1] = classOb
	tree[maxKey+2] = playerOb
	# Make loads reference player.
	loadTemplate = {"object": "triplex_load",
		"power_pf_12": "0.95",
		"impedance_pf_12": "0.98",
		"power_pf_12": "0.90",
		"impedance_fraction_12": "0.7",
		"power_fraction_12": "0.3"}
	for key in tree:
		ob = tree[key]
		if ob.get("object","") == "triplex_node" and ob.get("power_12","") != "":
			newOb = dict(loadTemplate)
			newOb["name"] = ob.get("name", "")
			newOb["parent"] = ob.get("parent", "")
			newOb["phases"] = ob.get("phases", "")
			newOb["nominal_voltage"] = ob.get("nominal_voltage","")
			newOb["latitude"] = ob.get("latitude","0")
			newOb["longitude"] = ob.get("longitude","0")
			oldPow = ob.get("power_12","").replace("j","d")
			pythagPower = gridlabd._strClean(oldPow)
			newOb["base_power_12"] = "scadaLoads.value*" + str(pythagPower)
			tree[key] = newOb
	# Search for the substation regulator and attach a recorder there.
	for key in tree:
		if tree[key].get('bustype','').lower() == 'swing':
			swingName = tree[key].get('name')
	for key in tree:
		if tree[key].get('object','') == 'regulator' and tree[key].get('from','') == swingName:
			regIndex = key
			SUB_REG_NAME = tree[key]['name']
	recOb = {"object": "recorder",
		"parent": SUB_REG_NAME,
		"property": "power_in.real,power_in.imag",
		"file": "caliSub.csv",
		"interval": "900"}
	tree[maxKey + 3] = recOb
	HOURS = 100
	feeder.adjustTime(tree, HOURS, "hours", "2011-01-01")
	# Run Gridlabd.
	output = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=workDir)
	# Calculate scaling constant.
	outRealPow = output["caliSub.csv"]["power_in.real"]
	outImagPower = output["caliSub.csv"]["power_in.imag"]
	outAppPowerKw = [(x[0]**2 + x[1]**2)**0.5/1000 for x in zip(outRealPow, outImagPower)]
	# HACK: ignore first time step in output and input because GLD sometimes breaks the first step.
	SCAL_CONST = sum(scadaSubPower[1:HOURS])/sum(outAppPowerKw[1:HOURS])
	# Rewrite the subScada.player file so all the power values are multiplied by the SCAL_CONSTANT.
	newPlayData = []
	with open(pJoin(workDir, "subScada.player"), "r") as playerFile:
		for line in playerFile:
			(key,val) = line.split(',')
			newPlayData.append(str(key) + ',' + str(float(val)*SCAL_CONST) + "\n")
	with open(pJoin(workDir, "subScadaCalibrated.player"), "w") as playerFile:
		for row in newPlayData:
			playerFile.write(row)
	# Test by running a glm with subScadaCalibrated.player and caliSub.csv2.
	tree[maxKey+2]["file"] = "subScadaCalibrated.player"
	tree[maxKey + 3]["file"] = "caliSubCheck.csv"
	secondOutput = gridlabd.runInFilesystem(tree, keepFiles=True, workDir=workDir)
	plt.plot(outAppPowerKw[1:HOURS], label="initialGuess")
	plt.plot(scadaSubPower[1:HOURS], label="scadaSubPower")
	secondAppKw = [(x[0]**2 + x[1]**2)**0.5/1000
		for x in zip(secondOutput["caliSubCheck.csv"]["power_in.real"], secondOutput["caliSubCheck.csv"]["power_in.imag"])]
	plt.plot(secondAppKw[1:HOURS], label="finalGuess")
	plt.legend(loc=3)
	plt.savefig(pJoin(workDir,"caliCheckPlot.png"))
	# Write the final output.
	with open(pJoin(workDir,"calibratedFeeder.json"),"w") as outJson:
		playerString = open(pJoin(workDir,"subScadaCalibrated.player")).read()
		feederJson["attachments"]["subScadaCalibrated.player"] = playerString
		feederJson["tree"] = tree
		json.dump(feederJson, outJson, indent=4)
	return
def heavyProcessing(modelDir, inputDict):
	''' Run the model in its directory. WARNING: GRIDLAB CAN TAKE HOURS TO COMPLETE. '''
	print "STARTING TO RUN", modelDir
	beginTime = datetime.datetime.now()
	# Get feeder name and data in.
	try: os.mkdir(pJoin(modelDir,'gldContainer'))
	except: pass
	try:	
		feederName = inputDict["feederName1"]
		inputDict["climateName"], latforpvwatts = zipCodeToClimateName(inputDict["zipCode"])
		shutil.copy(pJoin(__metaModel__._omfDir, "data", "Climate", inputDict["climateName"] + ".tmy2"),
			pJoin(modelDir, "gldContainer", "climate.tmy2"))
		startTime = datetime.datetime.now()
		feederJson = json.load(open(pJoin(modelDir, feederName+'.omd')))
		tree = feederJson["tree"]
		# Set up GLM with correct time and recorders:
		feeder.attachRecorders(tree, "Regulator", "object", "regulator")
		feeder.attachRecorders(tree, "Capacitor", "object", "capacitor")
		feeder.attachRecorders(tree, "Inverter", "object", "inverter")
		feeder.attachRecorders(tree, "Windmill", "object", "windturb_dg")
		feeder.attachRecorders(tree, "CollectorVoltage", None, None)
		feeder.attachRecorders(tree, "Climate", "object", "climate")
		feeder.attachRecorders(tree, "OverheadLosses", None, None)
		feeder.attachRecorders(tree, "UndergroundLosses", None, None)
		feeder.attachRecorders(tree, "TriplexLosses", None, None)
		feeder.attachRecorders(tree, "TransformerLosses", None, None)
		feeder.groupSwingKids(tree)
		# Attach recorders for system voltage map:
		stub = {'object':'group_recorder', 'group':'"class=node"', 'property':'voltage_A', 'interval':3600, 'file':'aVoltDump.csv'}
		for phase in ['A','B','C']:
			copyStub = dict(stub)
			copyStub['property'] = 'voltage_' + phase
			copyStub['file'] = phase.lower() + 'VoltDump.csv'
			tree[feeder.getMaxKey(tree) + 1] = copyStub
		feeder.adjustTime(tree=tree, simLength=float(inputDict["simLength"]),
			simLengthUnits=inputDict["simLengthUnits"], simStartDate=inputDict["simStartDate"])
		# RUN GRIDLABD IN FILESYSTEM (EXPENSIVE!)
		rawOut = gridlabd.runInFilesystem(tree, attachments=feederJson["attachments"], 
			keepFiles=True, workDir=pJoin(modelDir,'gldContainer'))
		cleanOut = {}
		# Std Err and Std Out
		cleanOut['stderr'] = rawOut['stderr']
		cleanOut['stdout'] = rawOut['stdout']
		# Time Stamps
		for key in rawOut:
			if '# timestamp' in rawOut[key]:
				cleanOut['timeStamps'] = rawOut[key]['# timestamp']
				break
			elif '# property.. timestamp' in rawOut[key]:
				cleanOut['timeStamps'] = rawOut[key]['# property.. timestamp']
			else:
				cleanOut['timeStamps'] = []
		# Day/Month Aggregation Setup:
		stamps = cleanOut.get('timeStamps',[])
		level = inputDict.get('simLengthUnits','hours')
		# Climate
		for key in rawOut:
			if key.startswith('Climate_') and key.endswith('.csv'):
				cleanOut['climate'] = {}
				cleanOut['climate']['Rain Fall (in/h)'] = hdmAgg(rawOut[key].get('rainfall'), sum, level)
				cleanOut['climate']['Wind Speed (m/s)'] = hdmAgg(rawOut[key].get('wind_speed'), avg, level)
				cleanOut['climate']['Temperature (F)'] = hdmAgg(rawOut[key].get('temperature'), max, level)
				cleanOut['climate']['Snow Depth (in)'] = hdmAgg(rawOut[key].get('snowdepth'), max, level)
				cleanOut['climate']['Direct Normal (W/sf)'] = hdmAgg(rawOut[key].get('solar_direct'), sum, level)
				#cleanOut['climate']['Global Horizontal (W/sf)'] = hdmAgg(rawOut[key].get('solar_global'), sum, level)	
				climateWbySFList= hdmAgg(rawOut[key].get('solar_global'), sum, level)
				#converting W/sf to W/sm
				climateWbySMList= [x*10.76392 for x in climateWbySFList]
				cleanOut['climate']['Global Horizontal (W/sm)']=climateWbySMList			
		# Voltage Band
		if 'VoltageJiggle.csv' in rawOut:
			cleanOut['allMeterVoltages'] = {}
			cleanOut['allMeterVoltages']['Min'] = hdmAgg([float(i / 2) for i in rawOut['VoltageJiggle.csv']['min(voltage_12.mag)']], min, level)
			cleanOut['allMeterVoltages']['Mean'] = hdmAgg([float(i / 2) for i in rawOut['VoltageJiggle.csv']['mean(voltage_12.mag)']], avg, level)
			cleanOut['allMeterVoltages']['StdDev'] = hdmAgg([float(i / 2) for i in rawOut['VoltageJiggle.csv']['std(voltage_12.mag)']], avg, level)
			cleanOut['allMeterVoltages']['Max'] = hdmAgg([float(i / 2) for i in rawOut['VoltageJiggle.csv']['max(voltage_12.mag)']], max, level)
		# Power Consumption
		cleanOut['Consumption'] = {}
		# Set default value to be 0, avoiding missing value when computing Loads
		cleanOut['Consumption']['Power'] = [0] * int(inputDict["simLength"])
		cleanOut['Consumption']['Losses'] = [0] * int(inputDict["simLength"])
		cleanOut['Consumption']['DG'] = [0] * int(inputDict["simLength"])
		for key in rawOut:
			if key.startswith('SwingKids_') and key.endswith('.csv'):
				oneSwingPower = hdmAgg(vecPyth(rawOut[key]['sum(power_in.real)'],rawOut[key]['sum(power_in.imag)']), avg, level)
				if 'Power' not in cleanOut['Consumption']:
					cleanOut['Consumption']['Power'] = oneSwingPower
				else:
					cleanOut['Consumption']['Power'] = vecSum(oneSwingPower,cleanOut['Consumption']['Power'])
			elif key.startswith('Inverter_') and key.endswith('.csv'): 	
				realA = rawOut[key]['power_A.real']
				realB = rawOut[key]['power_B.real']
				realC = rawOut[key]['power_C.real']
				imagA = rawOut[key]['power_A.imag']
				imagB = rawOut[key]['power_B.imag']
				imagC = rawOut[key]['power_C.imag']
				oneDgPower = hdmAgg(vecSum(vecPyth(realA,imagA),vecPyth(realB,imagB),vecPyth(realC,imagC)), avg, level)
				if 'DG' not in cleanOut['Consumption']:
					cleanOut['Consumption']['DG'] = oneDgPower
				else:
					cleanOut['Consumption']['DG'] = vecSum(oneDgPower,cleanOut['Consumption']['DG'])
			elif key.startswith('Windmill_') and key.endswith('.csv'):
				vrA = rawOut[key]['voltage_A.real']
				vrB = rawOut[key]['voltage_B.real']
				vrC = rawOut[key]['voltage_C.real']
				viA = rawOut[key]['voltage_A.imag']
				viB = rawOut[key]['voltage_B.imag']
				viC = rawOut[key]['voltage_C.imag']
				crB = rawOut[key]['current_B.real']
				crA = rawOut[key]['current_A.real']
				crC = rawOut[key]['current_C.real']
				ciA = rawOut[key]['current_A.imag']
				ciB = rawOut[key]['current_B.imag']
				ciC = rawOut[key]['current_C.imag']
				powerA = vecProd(vecPyth(vrA,viA),vecPyth(crA,ciA))
				powerB = vecProd(vecPyth(vrB,viB),vecPyth(crB,ciB))
				powerC = vecProd(vecPyth(vrC,viC),vecPyth(crC,ciC))
				oneDgPower = hdmAgg(vecSum(powerA,powerB,powerC), avg, level)
				if 'DG' not in cleanOut['Consumption']:
					cleanOut['Consumption']['DG'] = oneDgPower
				else:
					cleanOut['Consumption']['DG'] = vecSum(oneDgPower,cleanOut['Consumption']['DG'])
			elif key in ['OverheadLosses.csv', 'UndergroundLosses.csv', 'TriplexLosses.csv', 'TransformerLosses.csv']:
				realA = rawOut[key]['sum(power_losses_A.real)']
				imagA = rawOut[key]['sum(power_losses_A.imag)']
				realB = rawOut[key]['sum(power_losses_B.real)']
				imagB = rawOut[key]['sum(power_losses_B.imag)']
				realC = rawOut[key]['sum(power_losses_C.real)']
				imagC = rawOut[key]['sum(power_losses_C.imag)']
				oneLoss = hdmAgg(vecSum(vecPyth(realA,imagA),vecPyth(realB,imagB),vecPyth(realC,imagC)), avg, level)
				if 'Losses' not in cleanOut['Consumption']:
					cleanOut['Consumption']['Losses'] = oneLoss
				else:
					cleanOut['Consumption']['Losses'] = vecSum(oneLoss,cleanOut['Consumption']['Losses'])
			elif key.startswith('Regulator_') and key.endswith('.csv'):
				#split function to strip off .csv from filename and user rest of the file name as key. for example- Regulator_VR10.csv -> key would be Regulator_VR10
				regName=""
				regName = key
				newkey=regName.split(".")[0]
				cleanOut[newkey] ={}
				cleanOut[newkey]['RegTapA'] = [0] * int(inputDict["simLength"])
				cleanOut[newkey]['RegTapB'] = [0] * int(inputDict["simLength"])
				cleanOut[newkey]['RegTapC'] = [0] * int(inputDict["simLength"])
				cleanOut[newkey]['RegTapA'] = rawOut[key]['tap_A']
				cleanOut[newkey]['RegTapB'] = rawOut[key]['tap_B']
				cleanOut[newkey]['RegTapC'] = rawOut[key]['tap_C']
				cleanOut[newkey]['RegPhases'] = rawOut[key]['phases'][0]
			elif key.startswith('Capacitor_') and key.endswith('.csv'):
				capName=""
				capName = key
				newkey=capName.split(".")[0]
				cleanOut[newkey] ={}
				cleanOut[newkey]['Cap1A'] = [0] * int(inputDict["simLength"])
				cleanOut[newkey]['Cap1B'] = [0] * int(inputDict["simLength"])
				cleanOut[newkey]['Cap1C'] = [0] * int(inputDict["simLength"])
				cleanOut[newkey]['Cap1A'] = rawOut[key]['switchA']
				cleanOut[newkey]['Cap1B'] = rawOut[key]['switchB']
				cleanOut[newkey]['Cap1C'] = rawOut[key]['switchC']
				cleanOut[newkey]['CapPhases'] = rawOut[key]['phases'][0]
		# What percentage of our keys have lat lon data?
		latKeys = [tree[key]['latitude'] for key in tree if 'latitude' in tree[key]]
		latPerc = 1.0*len(latKeys)/len(tree)
		if latPerc < 0.25: doNeato = True
		else: doNeato = False
		# Generate the frames for the system voltage map time traveling chart.
		genTime = generateVoltChart(tree, rawOut, modelDir, neatoLayout=doNeato)
		cleanOut['genTime'] = genTime
		# Aggregate up the timestamps:
		if level=='days':
			cleanOut['timeStamps'] = aggSeries(stamps, stamps, lambda x:x[0][0:10], 'days')
		elif level=='months':
			cleanOut['timeStamps'] = aggSeries(stamps, stamps, lambda x:x[0][0:7], 'months')
		# Write the output.
		with open(pJoin(modelDir, "allOutputData.json"),"w") as outFile:
			json.dump(cleanOut, outFile, indent=4)
		# 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)
		# Clean up the PID file.
		os.remove(pJoin(modelDir, "gldContainer", "PID.txt"))
		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)
	finishTime = datetime.datetime.now()
	inputDict["runTime"] = str(datetime.timedelta(seconds = int((finishTime - beginTime).total_seconds())))
	with open(pJoin(modelDir, "allInputData.json"),"w") as inFile:
		json.dump(inputDict, inFile, indent = 4)
	try:
		os.remove(pJoin(modelDir,"PPID.txt"))
	except:
		pass