Skip to content

Commit

Permalink
derUtilityCost.py & .html: Added input options and reopt funtions
Browse files Browse the repository at this point in the history
  • Loading branch information
astronobri committed May 18, 2024
1 parent e8b1112 commit 467d87d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 40 deletions.
32 changes: 16 additions & 16 deletions omf/models/derUtilityCost.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,24 @@
<input type="number" id="analysis_years" name="analysis_years" value="{{allInputDataDict.analysis_years}}" step="1" min="2" max="75" required="required"/>
</div>
<div class="shortInput">
<label class="tooltip">Solar<span class="classic">Include solar?</span></label>
<select id="solar" name="solar" value="{{allInputDataDict.solar}}"/>
<option value="on" {{ 'selected' if allInputDataDict.solar == 'on' }}>Yes</option>
<option value="off" {{ 'selected' if allInputDataDict.solar == 'off' }}>No</option>
<label class="tooltip">PV<span class="classic">Include PV in DER analysis.</span></label>
<select id="PV" name="PV" value="{{allInputDataDict.PV}}"/>
<option value="Yes" {{ 'selected' if allInputDataDict.solar == 'Yes' }}>Yes</option>
<option value="No" {{ 'selected' if allInputDataDict.solar == 'No' }}>No</option>
</select>
</div>
<div class="shortInput">
<label class="tooltip">Battery<span class="classic">Include batteries?</span></label>
<select id="battery" name="battery" value="{{allInputDataDict.battery}}"/>
<option value="on" {{ 'selected' if allInputDataDict.battery == 'on' }}>Yes</option>
<option value="off" {{ 'selected' if allInputDataDict.battery == 'off' }}>No</option>
<label class="tooltip">Battery<span class="classic">Include battery energy storage in DER analysis.</span></label>
<select id="battery" name="battery" value="{{allInputDataDict.BESS}}"/>
<option value="Yes" {{ 'selected' if allInputDataDict.BESS == 'Yes' }}>Yes</option>
<option value="No" {{ 'selected' if allInputDataDict.BESS == 'No' }}>No</option>
</select>
</div>
<div class="shortInput">
<label class="tooltip">Generator<span class="classic">Include generator?</span></label>
<label class="tooltip">Diesel Generator<span class="classic">Include diesel generator in DER analysis.</span></label>
<select id="generator" name="generator" value="{{allInputDataDict.generator}}"/>
<option value="on" {{ 'selected' if allInputDataDict.generator == 'on' }}>Yes</option>
<option value="off" {{ 'selected' if allInputDataDict.generator == 'off' }}>No</option>
<option value="Yes" {{ 'selected' if allInputDataDict.generator == 'Yes' }}>Yes</option>
<option value="No" {{ 'selected' if allInputDataDict.generator == 'No' }}>No</option>
</select>
</div>
<div class="wideInput">
Expand All @@ -108,17 +108,17 @@
<div class="shortInput">
<label>Simulate Outage</label>
<select id="outage" name="outage" value="{{allInputDataDict.outage}}">
<option value="on" {{ 'selected' if allInputDataDict.outage == 'on' }}>On</option>
<option value="off" {{ 'selected' if allInputDataDict.outage == 'off' }}>Off</option>
<option value="True" {{ 'selected' if allInputDataDict.outage == 'True' }}>On</option>
<option value="False" {{ 'selected' if allInputDataDict.outage == 'False' }}>Off</option>
</select>
</div>
<div class="shortInput">
<label class="tooltip">Outage Start Hour<span class="classic">A major outage is added starting at this hour. Specify an hour greater than 0 but less than 8760 to trigger optimization for resilience and include fossil generation. If 0 is entered, the model will run an economic optimization without fossil generation.</span></label>
<label class="tooltip">Outage Start Hour<span class="classic">The starting hour of the outage. Specify an hour greater than 0 but less than 8760 to trigger optimization for resilience. If 0 is entered, the model will run an economic optimization without fossil generation.</span></label>
<input type="number" id="outage_start_hour" name="outage_start_hour" value="{{allInputDataDict.outage_start_hour}}" min="0" max="8760" required="required"/>
</div>
<div class="shortInput">
<label class="tooltip">Outage Duration (hours)<span class="classic">The added major outage is given this duration.</span></label>
<input type="number" id="outageDuration" name="outageDuration" value="{{allInputDataDict.outageDuration}}" min="1" max="8760" required="required"/>
<label class="tooltip">Outage Duration (hours)<span class="classic">The duration (in hours) of the outage. Specify a number between 1 - 8760 hours. </span></label>
<input type="number" id="outage_duration" name="outage_duration" value="{{allInputDataDict.outage_duration}}" min="1" max="8760" required="required"/>
</div>
<div class="wideInput"> <!-- vbatDispatch Specific Inputs -->
<p class="inputSectionHeader">Specific vbatDispatch Model Inputs</p>
Expand Down
54 changes: 30 additions & 24 deletions omf/models/derUtilityCost.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ def work(modelDir, inputDict):

## NOTE: This code will be used once reopt_jl is working
## Run REopt.jl
#outage_flag = inputDict['outage'] #TODO: Add outage option to HTML
#reopt_jl.run_reopt_jl(modelDir, reopt_input_scenario, outages=outage_flag)
outage_flag = inputDict['outage']

reopt_jl.run_reopt_jl(modelDir, "reopt_input_scenario.json", outages=outage_flag)
with open(pJoin(modelDir, 'results.json')) as jsonFile:
reoptResults = json.load(jsonFile)
outData.update(reoptResults) ## Update output file with reopt results

## NOTE: This code is temporary
## Read in a static REopt test file
Expand All @@ -50,14 +54,29 @@ def work(modelDir, inputDict):
print('Successfully read in REopt test file. \n')

## Create timestamp array from REopt input information
year = reoptResults['inputs.ElectricLoad.year'][0]
arr_size = np.size(reoptResults['outputs.ElectricUtility.electric_to_load_series_kw'][0])
try:
year = reoptResults['ElectricLoad.year'][0]
except KeyError:
year = inputDict['year'] # Use the user provided year if none found in reoptResults

arr_size = np.size(reoptResults['ElectricUtility']['electric_to_load_series_kw'])
timestamps = derConsumer.create_timestamps(start_time=f'{year}-01-01', end_time=f'{year}-12-31 23:00:00', arr_size=arr_size)

## Convert temperature data from str to float
temperatures = [float(value) for value in inputDict['tempCurve'].split('\n') if value.strip()]
demand = np.asarray([float(value) for value in inputDict['demandCurve'].split('\n') if value.strip()])

## If outage is specified, load the resilience results
if (inputDict['outage']):
try:
with open(pJoin(modelDir, 'resultsResilience.json')) as jsonFile:
reoptResultsResilience = json.load(jsonFile)
outData.update(reoptResultsResilience) ## Update out file with resilience results
except FileNotFoundError:
results_file = pJoin(modelDir, 'resultsResilience.json')
print(f"File '{results_file}' not found. REopt may not have simulated the outage.")
raise

## Run vbatDispatch
vbatResults = vb.work(modelDir,inputDict)
with open(pJoin(modelDir, 'vbatResults.json'), 'w') as jsonFile:
Expand All @@ -80,18 +99,6 @@ def work(modelDir, inputDict):

#reopt_jl.run_reopt_jl(path="/Users/astronobri/Documents/CIDER/reopt/inputs/", inputFile="UP_PV_outage_1hr.json", outages=outage) # UP coop PV
#reopt_jl.run_reopt_jl(path="/Users/astronobri/Documents/CIDER/reopt/inputs/", inputFile=pJoin(__neoMetaModel__._omfDir,"static","testFiles","residential_input.json"), outages=True) # residential PV


inputDict['outage'] = False ##NOTE: Temporary line to disable the following outage resilience code
if (inputDict['outage']):
try:
with open(pJoin(modelDir, 'resultsResilience.json')) as jsonFile:
resultsResilience = json.load(jsonFile)
outData.update(resultsResilience) ## Update out file with resilience results
except FileNotFoundError:
results_file = pJoin(modelDir, 'resultsResilience.json')
print(f"File '{results_file}' not found.")
raise

## Test plot
showlegend = False #temporarily disable the legend toggle
Expand Down Expand Up @@ -208,7 +215,6 @@ def work(modelDir, inputDict):
outData['plotlyPlot'] = json.dumps(fig.data, cls=plotly.utils.PlotlyJSONEncoder)
outData['plotlyLayout'] = json.dumps(fig.layout, cls=plotly.utils.PlotlyJSONEncoder)


# Model operations typically ends here.
# Stdout/stderr.
outData["stdout"] = "Success"
Expand All @@ -230,23 +236,23 @@ def new(modelDir):

## REopt inputs:
"latitude" : '39.7392358',
"longitude" : '-104.990251',
"longitude" : '-104.990251', ## Brighton, CO
"year" : '2018',
"analysis_years" : '25',
"urdbLabel" : '612ff9c15457a3ec18a5f7d3', ## Brighton, CO - United Power
"urdbLabel" : '612ff9c15457a3ec18a5f7d3', ## Brighton, CO
"fileName": "utility_2018_kW_load.csv",
"tempFileName": "utility_CO_2018_temperatures.csv",
"demandCurve": demand_curve,
"tempCurve": temp_curve,
"PV": "Yes",
"BESS": "No",
"generator": "No",
"outage": True,
"outage_start_hour": '2100',
"outageDuration": '3',
"solar" : "on",
"battery" : "on",
"generator" : "off",
"outage_duration": '3',

## vbatDispatch inputs:
"load_type": "2",
"load_type": "2", ## Heat Pump
"number_devices": "1",
"power": "5.6",
"capacitance": "2",
Expand Down

0 comments on commit 467d87d

Please sign in to comment.