Skip to content

Commit

Permalink
fix hostingCapacity to work with new algo
Browse files Browse the repository at this point in the history
  • Loading branch information
dpinney committed Jul 27, 2023
1 parent e844840 commit e1344d6
Showing 1 changed file with 116 additions and 139 deletions.
255 changes: 116 additions & 139 deletions omf/models/hostingCapacity.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
''' Calculate solar photovoltaic system output using PVWatts. '''

''' Calculate hosting capacity using traditional and/or AMI-based methods. '''
import base64
import shutil
from os.path import join as pJoin
Expand All @@ -14,155 +13,133 @@
import omf
from omf.models import __neoMetaModel__
from omf.models.__neoMetaModel__ import *
from omf.models import derInterconnection
from omf.solvers import opendss

# Model metadata:
tooltip = "The hostingCapacity model calculates the kW hosting capacity available at each meter in the provided AMI data."
tooltip = "Calculate hosting capacity using traditional and/or AMI-based methods."
modelName, template = __neoMetaModel__.metadata(__file__)
hidden = False

def work(modelDir, inputDict):
outData = {}
import mohca_cl

with open(pJoin(modelDir,inputDict['inputDataFileName']),'w', newline='') as pv_stream:
pv_stream.write(inputDict['inputDataFileContent'])

inputPath = pJoin(modelDir, inputDict['inputDataFileName'])
outputPath = pJoin(modelDir, 'mohcaOutput.csv')

mohcaOutput = []
if inputDict[ "mohcaAlgorithm" ] == "sandia1":
mohcaOutput = mohca_cl.sandia1( inputPath, outputPath )
elif inputDict[ "mohcaAlgorithm" ] == "sandia2":
mohcaOutput = mohca_cl.sandia2( inputPath, outputPath )
else:
errorMessage = "Algorithm name error"
raise Exception(errorMessage)

mohcaResults = mohcaOutput[0].rename(columns={'kW_hostable': 'voltage_cap_kW'})

mohcaHistogramFigure = px.histogram( mohcaResults, x='voltage_cap_kW', template="simple_white", color_discrete_sequence=["MediumPurple"] )
mohcaHistogramFigure.update_layout(bargap=0.5)

barChartDF = mohcaResults
barChartDF['thermal_cap'] = [1]
barChartDF['max_cap_kW'] = np.minimum( barChartDF['voltage_cap_kW'], barChartDF['thermal_cap'])

mohcaBarChartFigure = px.bar(barChartDF, x='busname', y=['voltage_cap_kW', 'thermal_cap', 'max_cap_kW'], barmode='group', color_discrete_sequence=["green", "lightblue", "MediumPurple"], template="simple_white" )
# mohcaBarChartFigure.update_layout()

# Line graph of the data
# timeSeriesFigure = px.line( mohcaResults.sort_values( by="kW_hostable", ascending=False, ignore_index=True ), x='busname', y='kW_hostable', markers=True, color_discrete_sequence=['purple', "blue", "green"])
# timeSeriesFigure.update_yaxes(rangemode="tozero") # This line sets the base of the y axis to be 0.

# traditional hosting capacity
# if they uploaded an omd circuit file
circuitFileStatus = inputDict.get('optionalCircuitFile', 0)
print('STATUS!', circuitFileStatus, inputDict.get('optionalCircuitFile', 0))
if ( circuitFileStatus == 'on' ):
feederName = [x for x in os.listdir(modelDir) if x.endswith('.omd')][0]
inputDict['feederName1'] = feederName
omd = json.load(open(pJoin(modelDir, feederName)))
tree = omd.get('tree',{})
#for k, v in omd['tree'].items():

# once we take the omd file and convert it to a tree, we can loop through the objects to find all the 'bus' objects, that can be our second input
# then there are option inputs for the step and kw for the user to put in? idk
# print( os.path.abspath(feederName) ) why is this in the omf directory and not the modelDir?
traditionalHCResults = omf.solvers.opendss.hosting_capacity_verbose(pJoin(modelDir, feederName), modelDir, ['701', '730', '703', '724'], int( inputDict["traditionalHCSteps"] ), int( inputDict["traditionalHCkW"] ))
tradHCDF = traditionalHCResults[0]
print( tradHCDF )

omf.geo.map_omd(pJoin(modelDir, feederName), modelDir, open_browser=False )
# outData['traditionalHCMap'] = pJoin( modelDir, 'geoJson_offline.html')
outData['traditionalHCMap'] = open( pJoin( modelDir, "geoJson_offline.html"), 'r' ).read()

traditionalHCFigure = make_subplots(specs=[[{"secondary_y": True }]])
traditionalHCFigure.add_trace(
go.Scatter( x = tradHCDF.index, y = tradHCDF["kw_add"], name= "kw_add"),
secondary_y=False
)
traditionalHCFigure.add_trace(
go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu1"], name= "v_max_pu1"),
secondary_y=True
)
traditionalHCFigure.add_trace(
go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu2"], name= "v_max_pu2"),
secondary_y=True
)
traditionalHCFigure.add_trace(
go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu3"], name= "v_max_pu3"),
secondary_y=True
)
traditionalHCFigure.add_trace(
go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_all_pu"], name= "v_max_all_pu"),
secondary_y=True
)
traditionalHCFigure.update_yaxes( title_text="<b>Voltage ( PU )</b>", secondary_y = False)
traditionalHCFigure.update_yaxes( title_text="<b>Total Additional Generation Added ( kW ) </b>", secondary_y = True)
outData['traditionalGraphData'] = json.dumps( traditionalHCFigure, cls=py.utils.PlotlyJSONEncoder )
outData['traditionalHCTableHeadings'] = traditionalHCResults[0].columns.values.tolist()
outData['traditionalHCTableValues'] = ( list( traditionalHCResults[0].itertuples(index=False, name=None)))

# Stdout/stderr.
outData['stdout'] = "Success"
outData['stderr'] = ""
outData['mohcaHistogramFigure'] = json.dumps( mohcaHistogramFigure, cls=py.utils.PlotlyJSONEncoder )
outData['mohcaBarChartFigure'] = json.dumps( mohcaBarChartFigure, cls=py.utils.PlotlyJSONEncoder )
outData['mohcaHCTableHeadings'] = mohcaResults.columns.values.tolist()
outData['mohcaHCTableValues'] = ( list(mohcaResults.sort_values( by="voltage_cap_kW", ascending=False, ignore_index=True ).itertuples(index=False, name=None)) ) #NOTE: kW_hostable

# Stdout/stderr.
outData['stdout'] = "Success"
outData['stderr'] = ""
return outData
outData = {}
import mohca_cl
with open(pJoin(modelDir,inputDict['inputDataFileName']),'w', newline='') as pv_stream:
pv_stream.write(inputDict['inputDataFileContent'])
inputPath = pJoin(modelDir, inputDict['inputDataFileName'])
outputPath = pJoin(modelDir, 'mohcaOutput.csv')
mohcaOutput = []
if inputDict[ "mohcaAlgorithm" ] == "sandia1":
mohcaOutput = mohca_cl.sandia1( inputPath, outputPath )
elif inputDict[ "mohcaAlgorithm" ] == "sandia2":
mohcaOutput = mohca_cl.sandia2( inputPath, outputPath )
else:
errorMessage = "Algorithm name error"
raise Exception(errorMessage)
mohcaResults = mohcaOutput[0].rename(columns={'kW_hostable': 'voltage_cap_kW'})
mohcaHistogramFigure = px.histogram( mohcaResults, x='voltage_cap_kW', template="simple_white", color_discrete_sequence=["MediumPurple"] )
mohcaHistogramFigure.update_layout(bargap=0.5)
barChartDF = mohcaResults
barChartDF['thermal_cap'] = [1]
barChartDF['max_cap_kW'] = np.minimum( barChartDF['voltage_cap_kW'], barChartDF['thermal_cap'])
mohcaBarChartFigure = px.bar(barChartDF, x='busname', y=['voltage_cap_kW', 'thermal_cap', 'max_cap_kW'], barmode='group', color_discrete_sequence=["green", "lightblue", "MediumPurple"], template="simple_white" )
# mohcaBarChartFigure.update_layout()
# Line graph of the data
# timeSeriesFigure = px.line( mohcaResults.sort_values( by="kW_hostable", ascending=False, ignore_index=True ), x='busname', y='kW_hostable', markers=True, color_discrete_sequence=['purple', "blue", "green"])
# timeSeriesFigure.update_yaxes(rangemode="tozero") # This line sets the base of the y axis to be 0.
# traditional hosting capacity
# if they uploaded an omd circuit file
circuitFileStatus = inputDict.get('optionalCircuitFile', 0)
print('STATUS!', circuitFileStatus, inputDict.get('optionalCircuitFile', 0))
if ( circuitFileStatus == 'on' ):
feederName = [x for x in os.listdir(modelDir) if x.endswith('.omd')][0]
inputDict['feederName1'] = feederName
tree = opendss.dssConvert.omdToTree(pJoin(modelDir, feederName))
opendss.dssConvert.treeToDss(tree, pJoin(modelDir, 'circuit.dss'))
traditionalHCResults = opendss.hosting_capacity_all(pJoin(modelDir, 'circuit.dss'), int(inputDict["traditionalHCSteps"]), int(inputDict["traditionalHCkW"]))
tradHCDF = pd.DataFrame(traditionalHCResults)
print('TRADREZ', traditionalHCResults)
omf.geo.map_omd(pJoin(modelDir, feederName), modelDir, open_browser=False )
outData['traditionalHCMap'] = open( pJoin( modelDir, "geoJson_offline.html"), 'r' ).read()
traditionalHCFigure = make_subplots(specs=[[{"secondary_y": True }]])
traditionalHCFigure.add_trace(
go.Scatter( x = tradHCDF.index, y = tradHCDF["max_kw"], name= "max_kw"),
secondary_y=False
)
# traditionalHCFigure.add_trace(
# go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu1"], name= "v_max_pu1"),
# secondary_y=True
# )
# traditionalHCFigure.add_trace(
# go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu2"], name= "v_max_pu2"),
# secondary_y=True
# )
# traditionalHCFigure.add_trace(
# go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu3"], name= "v_max_pu3"),
# secondary_y=True
# )
# traditionalHCFigure.add_trace(
# go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_all_pu"], name= "v_max_all_pu"),
# secondary_y=True
# )
# traditionalHCFigure.update_yaxes( title_text="<b>Voltage ( PU )</b>", secondary_y = False)
traditionalHCFigure.update_yaxes( title_text="<b>Total Additional Generation Added ( kW ) </b>", secondary_y = True)
outData['traditionalGraphData'] = json.dumps( traditionalHCFigure, cls=py.utils.PlotlyJSONEncoder )
# outData['traditionalHCTableHeadings'] = traditionalHCResults[0].columns.values.tolist()
# outData['traditionalHCTableValues'] = ( list( traditionalHCResults[0].itertuples(index=False, name=None)))
# Stdout/stderr.
outData['stdout'] = "Success"
outData['stderr'] = ""
outData['mohcaHistogramFigure'] = json.dumps( mohcaHistogramFigure, cls=py.utils.PlotlyJSONEncoder )
outData['mohcaBarChartFigure'] = json.dumps( mohcaBarChartFigure, cls=py.utils.PlotlyJSONEncoder )
outData['mohcaHCTableHeadings'] = mohcaResults.columns.values.tolist()
outData['mohcaHCTableValues'] = ( list(mohcaResults.sort_values( by="voltage_cap_kW", ascending=False, ignore_index=True ).itertuples(index=False, name=None)) ) #NOTE: kW_hostable
return outData

def runtimeEstimate(modelDir):
''' Estimated runtime of model in minutes. '''
return 0.5
''' Estimated runtime of model in minutes. '''
return 0.5

def new(modelDir):
''' Create a new instance of this model. Returns true on success, false on failure. '''
test_file_name = 'sandia_loc1_test_data.csv'
test_file_path = pJoin(omf.omfDir,'static','testFiles', test_file_name)
test_circuit_name = "ieee37_LBL"
test_file_contents = open(test_file_path).read()
defaultInputs = {
"mohcaAlgorithm": 'sandia1',
"feederName1": test_circuit_name,
"inputDataFileName": test_file_name,
"inputDataFileContent": test_file_contents,
"modelType": modelName,
"traditionalHCSteps": 10,
"optionalCircuitFile": 'on',
"traditionalHCkW": 1
}
creationCode = __neoMetaModel__.new(modelDir, defaultInputs)
try:
shutil.copyfile(pJoin(__neoMetaModel__._omfDir, "static", "hostingcapacityfiles", defaultInputs["feederName1"]+'.omd'), pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
except:
return False
return creationCode
''' Create a new instance of this model. Returns true on success, false on failure. '''
meter_file_name = 'sandia_loc1_test_data.csv'
meter_file_path = pJoin(omf.omfDir,'static','testFiles', meter_file_name)
meter_file_contents = open(meter_file_path).read()
defaultInputs = {
"modelType": modelName,
"mohcaAlgorithm": 'sandia1',
"inputDataFileName": meter_file_name,
"inputDataFileContent": meter_file_contents,
"feederName1": 'ieee37_LBL',
"traditionalHCSteps": 10,
"optionalCircuitFile": 'on',
"traditionalHCkW": 1
}
creationCode = __neoMetaModel__.new(modelDir, defaultInputs)
try:
shutil.copyfile(
pJoin(__neoMetaModel__._omfDir, "static", "hostingcapacityfiles", defaultInputs["feederName1"]+'.omd'),
pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
except:
return False
return creationCode

@neoMetaModel_test_setup
def _disabled_tests():
# Location
modelLoc = pJoin(__neoMetaModel__._omfDir,"data","Model","admin","Automated Testing of " + modelName)
# Blow away old test results if necessary.
try:
shutil.rmtree(modelLoc)
except:
# No previous test results.
pass
# Create New.
new(modelLoc)
# Pre-run.
__neoMetaModel__.renderAndShow(modelLoc)
# Run the model.
__neoMetaModel__.runForeground(modelLoc)
# Show the output.
__neoMetaModel__.renderAndShow(modelLoc)
# Location
modelLoc = pJoin(__neoMetaModel__._omfDir,"data","Model","admin","Automated Testing of " + modelName)
# Blow away old test results if necessary.
try:
shutil.rmtree(modelLoc)
except:
pass # No previous test results.
# Create New.
new(modelLoc)
# Pre-run.
__neoMetaModel__.renderAndShow(modelLoc)
# Run the model.
__neoMetaModel__.runForeground(modelLoc)
# Show the output.
__neoMetaModel__.renderAndShow(modelLoc)

if __name__ == '__main__':
_disabled_tests()
_disabled_tests()

0 comments on commit e1344d6

Please sign in to comment.