Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions omf/models/resilientCommunity.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,16 @@ def getDistribution():
def testRunCalculations():
pathToOmd = "C:/Users/louis/NRECA/omf/omf/static/testFiles/resilientCommunity/ieee37_LBL_simplified.omd"
modelDir = "C:/Users/louis/NRECA/omf/omf/static/testFiles/resilientCommunity"
feederName = "ieee37_LBL_simplified"
custInfoPath = pJoin(omf.omfDir,'static','testFiles','resilientCommunity','restorationLoads.csv')
avgPeakDemand = 1
avgNumOccupants = 4
equipmentList = ['lines', 'transformers', 'fuses']
oipInputDict = {'oip_poverty':1, 'oip_employed':1, 'oip_income':1}
oipAggMethod = 'Average of Min-Max-Normalized'
runCalculations(modelDir, pathToOmd, custInfoPath, avgPeakDemand, avgNumOccupants, equipmentList, oipInputDict, oipAggMethod)
runCalculations(modelDir, pathToOmd, custInfoPath, avgPeakDemand, avgNumOccupants, equipmentList, oipInputDict, oipAggMethod, feederName)

def runCalculations(modelDir, pathToOmd, custInfoPath, avgPeakDemand, avgNumOccupants, equipmentList, oipInputDict, oipAggMethod):
def runCalculations(modelDir, pathToOmd, custInfoPath, avgPeakDemand, avgNumOccupants, equipmentList, oipInputDict, oipAggMethod, feederName):
'''
Runs computations on circuit for different loads and equipment.
Creates a CSV called resilientCommunityOutput.csv in the modelDir
Expand Down Expand Up @@ -322,7 +323,7 @@ def runCalculations(modelDir, pathToOmd, custInfoPath, avgPeakDemand, avgNumOccu
restrictToResidential = useOipCustVars(oipInputDict)
loadDict, loadCoordsDict = makeLoadDicts(omd, sectionsDict, distanceDict, custInfoDF, restrictToResidential, avgPeakDemand, avgNumOccupants)
# create blockgroupDicts with Outage Impact Metric (OIP) for each blockgroup and provide messages about what variables had to be removed from the analysis
blockgroupDict, loads2BgDict = makeBlockgroupDicts(modelDir, loadCoordsDict)
blockgroupDict, loads2BgDict = makeBlockgroupDicts(modelDir, loadCoordsDict, feederName)
addOipToBlockgroups(blockgroupDict, oipInputDict, oipAggMethod)
# Add blockgroup info to loads and process it into new metrics in loadDict
addBgInfoToLoads(loadDict, blockgroupDict, loads2BgDict)
Expand Down Expand Up @@ -903,7 +904,7 @@ def addWeatherToBlockgroups(blockgroupDict):
weatherCode = wt.replace('_AFREQ','').lower()
blockgroupDict[bg][f'oip_af_{weatherCode}'] = weatherData

def makeBlockgroupDicts(modelDir, loadCoordsDict):
def makeBlockgroupDicts(modelDir, loadCoordsDict, feederName):
''' Constructs and returns blockgroupDict and loads2BgDict.

When returned, blockgroupDict contains blockgroups as keys and dictionaries as values for each blockgroup recorded with the following keys:
Expand All @@ -913,15 +914,21 @@ def makeBlockgroupDicts(modelDir, loadCoordsDict):

When returned, loads2BgDict contains loadKeys (e.g. load.s733) as keys and blockgroups as values.

Saves and loads blockgroupDict to/from a json file in modelDir to avoid redundant web calls across multiple runs.
Does not load if feederName has changed between runs to avoid cross-feeder contamination when new feeder is used.

'''
blockgroupDict = {}
loads2BgDict = {}

# Load blockgroupDict
# Load blockgroupDict (if the feederName hasn't changed since last run)
blockgroupDictFilePath = pJoin(modelDir, 'blockgroupDictData.json')
if isfile(blockgroupDictFilePath):
with open(blockgroupDictFilePath, 'r') as f:
blockgroupDict = json.load(f)
bgAndFeederNameDict = json.load(f)
previousFeederName = bgAndFeederNameDict.get('feederName')
if feederName == previousFeederName:
blockgroupDict = bgAndFeederNameDict.get('blockgroupDict',{})
# Build blockgroup entries that aren't already populated
webDataUpdated = False
for loadKey, coordsDict in loadCoordsDict.items():
Expand All @@ -939,7 +946,11 @@ def makeBlockgroupDicts(modelDir, loadCoordsDict):
# Save blockgroupDict if web-sourced contents were updated
if webDataUpdated:
with open(blockgroupDictFilePath, 'w') as f:
json.dump(blockgroupDict, f)
bgAndFeederNameDict = {
'feederName': feederName,
'blockgroupDict': blockgroupDict
}
json.dump(bgAndFeederNameDict, f)
# Add weather data to blockgroupDict. Done here rather than in the loop because it loads and unloads a big file and we only want to do that once per run.
addWeatherToBlockgroups(blockgroupDict)
return blockgroupDict, loads2BgDict
Expand Down Expand Up @@ -1345,6 +1356,7 @@ def createColorCSVBlockGroup(modelDir, loadsDict, objectsDict):
newobjectsDict = {k.split('.')[1]:v for k,v in objectsDict.items()}
combined_dict = {**newloadsDict, **newobjectsDict}
new_df = pd.DataFrame.from_dict(combined_dict, orient='index')
new_df = new_df.fillna(-1)
new_df[['base crit score','locational crit score','base crit index','locational crit index','section']].to_csv(pJoin(modelDir, 'color_by.csv'), index=True)

def copyInputFilesToModelDir(modelDir, inputDict):
Expand Down Expand Up @@ -1408,7 +1420,7 @@ def work(modelDir, inputDict):
restrictToResidential = useOipCustVars(oipInputDict)
loadDict, loadCoordsDict = makeLoadDicts(omd, sectionsDict, distanceDict, custInfoDF, restrictToResidential, inputDict['averageDemand'], inputDict['averageOccupants'])
# Create blockgroupDict
blockgroupDict, loads2BgDict = makeBlockgroupDicts(modelDir, loadCoordsDict)
blockgroupDict, loads2BgDict = makeBlockgroupDicts(modelDir, loadCoordsDict, feederName)
outData['rmMsgs'] = addOipToBlockgroups(blockgroupDict, oipInputDict, inputDict['oipAggMethod'])
# Add bg info to loads
addBgInfoToLoads(loadDict, blockgroupDict, loads2BgDict)
Expand Down Expand Up @@ -1524,12 +1536,13 @@ def work(modelDir, inputDict):
return outData

def new(modelDir):
omdfileName = 'iowa240_in_Florida_copy2'
#omdfileName = 'iowa240_in_Florida_copy2'
#omdfileName = 'iowa240_dwp_22_no_show_voltage.dss'
#omdfileName = 'ieee37_LBL_simplified'

omdfileName = 'iowa240_in_Florida_copy2_no_show_voltage.dss'

# Establish Default Files
customerFileName = [omf.omfDir,'static','testFiles','resilientCommunity','restorationLoads ORIGINAL.csv']
customerFileName = [omf.omfDir,'static','testFiles','resilientCommunity','restorationLoads.csv']
customerData = open(pJoin(*customerFileName)).read()
equipLifeFileName = [omf.omfDir,'static','testFiles','resilientCommunity','equipLifeExample.csv']
equipLifeData = open(pJoin(*equipLifeFileName)).read()
Expand Down Expand Up @@ -1584,7 +1597,8 @@ def new(modelDir):
creationCode = __neoMetaModel__.new(modelDir, defaultInputs)
try:
#shutil.copyfile(pJoin(__neoMetaModel__._omfDir, "static", "publicFeeders", defaultInputs["feederName1"]+'.omd'), pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
shutil.copyfile(pJoin(__neoMetaModel__._omfDir, "static", "testFiles","resilientCommunity", defaultInputs["feederName1"]+'.omd'), pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
#shutil.copyfile(pJoin(__neoMetaModel__._omfDir, "static", "testFiles","resilientCommunity", defaultInputs["feederName1"]+'.omd'), pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
shutil.copyfile(pJoin(__neoMetaModel__._omfDir, "static", "testFiles", defaultInputs["feederName1"]+'.omd'), pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
shutil.copyfile(pJoin(*customerFileName), pJoin(modelDir, defaultInputs["customerFileName"]))
shutil.copyfile(pJoin(*equipLifeFileName), pJoin(modelDir, defaultInputs["equipLifeFileName"]))
except:
Expand Down
18 changes: 9 additions & 9 deletions omf/models/restoration.html
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,11 @@
plotGraph("fig5Chart", allOutputData["fig5Data"], allOutputData["fig5Layout"])
</script>
</div>
<p class="reportTitle"><label class="tooltip">TAOFI Histogram<span class="classic">Time Average Outage Frequency Index (TAOFI) is calculated as 1/(the average period between the onset of outages in minutes) for a given load. A lower TAOFI value indicates more time between outages on average for a load.</span></label></p>
<p class="reportTitle" style="page-break-before:always">Utility Outage Cost</p>
<div id="utilityOutageCostCalc" class="tightContent">
{{ allOutputDataDict['utilityOutageHtml'] }}
</div>
<p class="reportTitle"><label class="tooltip">TAOFI Histogram<span class="classic">Time Average Outage Frequency Index (TAOFI) is calculated as 1/(the average period between the onset of outages in hours) for a given load. A lower TAOFI value indicates more time between outages on average for a load.</span></label></p>
<div id="taofiHist" class="tightContent">
<div id="taofiHistChart" style="width:1000px"></div>
<script type="text/javascript">
Expand Down Expand Up @@ -256,10 +260,6 @@
</script>
</div>
{% endif %}
<p class="reportTitle" style="page-break-before:always">Utility Outage Cost</p>
<div id="utilityOutageCostCalc" class="tightContent">
{{ allOutputDataDict['utilityOutageHtml'] }}
</div>
<p class="reportTitle"><label class="tooltip">Outage Incidence for Full System<span class="classic">Outage Incidence is the percent of loads in a system that are experiencing an outage at a given time. A load is considered to be experiencing an outage at a given time if its "After" status in the Timeline below is "offline".</span></label></p>
<div id="fig6" class="tightContent">
<div id="fig6Chart" style="width:1000px"></div>
Expand All @@ -278,10 +278,6 @@
}
</script>
</div>
<p class="reportTitle" style="page-break-before:always">Timeline</p>
<div id="outageCostCalc" class="tightContent sorttable" style="max-height:500px; overflow-y:scroll">
{{ allOutputDataDict['timelineStatsHtml'] }}
</div>
<p class="reportTitle" style="page-break-before:always"><label class="tooltip">Simulation-Constrained Metrics by Microgrid<span class="classic">LCI related metrics only consider loads in each microgrid that have LCI values.</span></label></p>
<div id="tradMetricsCalc" class="tightContent sorttable" style="max-height:500px; overflow-y:scroll">
{{ allOutputDataDict['tradMetricsHtml'] }}
Expand All @@ -292,6 +288,10 @@
{{ allOutputDataDict['lciQuartTradMetricsHtml'] }}
</div>
{% endif %}
<p class="reportTitle" style="page-break-before:always">Timeline</p>
<div id="outageCostCalc" class="tightContent sorttable" style="max-height:500px; overflow-y:scroll">
{{ allOutputDataDict['timelineStatsHtml'] }}
</div>
<!-- Leaflet map directly inline with model-->
<p class="reportTitle">Outage Map and Time Slider</p>
<div class="tightContent" style="margin-bottom:-1px">
Expand Down
Loading