Skip to content

Commit 7768ff6

Browse files
RE Optimization w/ Dynamic Surrogates (gmlc-dispatches#172)
* copy over to this branch * update setup.py * fix DoubleLoopOptimization.ipynb * fix DoubleLoopOptimization.ipynb * update * Update test_RE_flowsheet.py * add subscenario * add steadystate optimization * update results with steadystate surrogate * notebook order * notebook order * update results * update pysam version * update ymls * update ymls * update ymls * update ymls * update ymls * pull from git lfs * update setup.py * update notebooks * add tests * update test * start tests * add surrogate tests * update * update test_surrogate_opt * add to tests * addheader * minor edit * Update RE steady-state models to Tensorflow 2.10 * Fix typo * Try removing conditional skip for Windows * Add tests for model deserialization * Disable other tests while debugging * Fix typo in CI pytest flags * Pin to micro versions for serialized models for RE surrogates * Add test for RE dispatch surrogate * add working model hopefully * Add .gitattributes file to define files to be treated as binary by git * Revert "Disable other tests while debugging" This reverts commit bfa31ed. * Run addheader on new file * Apply addheader changes for a few unrelated files --------- Co-authored-by: Ludovico Bianchi <[email protected]>
1 parent a2a7bb9 commit 7768ff6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+40738
-2589
lines changed

.gitattributes

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# -text: do not apply line ending normalization
2+
# -merge: do not try to merge
3+
# `binary` can also be used corresponding to `-text -merge -diff`
4+
variables.data-* -text -merge
5+
variables.index -text -merge
6+
*.pb -text -merge
7+
*.pkl -text -merge
8+
*.srw -text -merge
9+
*.npy -text -merge
10+
*.png -text -merge

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ auto-save-list
5252
*_results/
5353
*_results_*/
5454
sim_*/
55-
dispatches/case_studies/nuclear_case/ARMA_Model/output/
55+
dispatches/case_studies/nuclear_case/ARMA_Model/output/
56+
results_PT*/

dispatches/case_studies/renewables_case/DoubleLoopOptimization.ipynb

+3-3
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,7 @@
21212121
],
21222122
"metadata": {
21232123
"kernelspec": {
2124-
"display_name": "Python 3 (ipykernel)",
2124+
"display_name": "test",
21252125
"language": "python",
21262126
"name": "python3"
21272127
},
@@ -2135,11 +2135,11 @@
21352135
"name": "python",
21362136
"nbconvert_exporter": "python",
21372137
"pygments_lexer": "ipython3",
2138-
"version": "3.8.10"
2138+
"version": "3.8.15 | packaged by conda-forge | (default, Nov 22 2022, 08:53:40) \n[Clang 14.0.6 ]"
21392139
},
21402140
"vscode": {
21412141
"interpreter": {
2142-
"hash": "adc8d912f68e00b9537545a6770175a33b2964eab7b9aa765dfe6c46c3a9402b"
2142+
"hash": "d3dad436d7b583223d0e31ae61be302c6770fbae8b699f712ac6b1e6b25e6a86"
21432143
}
21442144
}
21452145
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#################################################################################
2+
# DISPATCHES was produced under the DOE Design Integration and Synthesis Platform
3+
# to Advance Tightly Coupled Hybrid Energy Systems program (DISPATCHES), and is
4+
# copyright (c) 2020-2023 by the software owners: The Regents of the University
5+
# of California, through Lawrence Berkeley National Laboratory, National
6+
# Technology & Engineering Solutions of Sandia, LLC, Alliance for Sustainable
7+
# Energy, LLC, Battelle Energy Alliance, LLC, University of Notre Dame du Lac, et
8+
# al. All rights reserved.
9+
#
10+
# Please see the files COPYRIGHT.md and LICENSE.md for full copyright and license
11+
# information, respectively. Both files are also available online at the URL:
12+
# "https://github.com/gmlc-dispatches/dispatches".
13+
#################################################################################
14+
from idaes.apps.grid_integration.bidder import *
15+
from dispatches.workflow.parametrized_bidder import PerfectForecaster, ParametrizedBidder
16+
17+
18+
class PEMParametrizedBidder(ParametrizedBidder):
19+
"""
20+
Wind + PEM bidder that uses parameterized bid curve.
21+
22+
'pem_marginal_cost': the cost/MW above which all available wind energy will be sold to grid;
23+
below which, make hydrogen and sell remainder of wind to grid
24+
'pem_mw': maximum PEM capacity limits how much energy is bid at the `pem_marginal_cost`
25+
26+
Every timestep for RT or DA, max energy bid is the available wind resource
27+
"""
28+
29+
def __init__(
30+
self,
31+
bidding_model_object,
32+
day_ahead_horizon,
33+
real_time_horizon,
34+
solver,
35+
forecaster,
36+
pem_marginal_cost,
37+
pem_mw
38+
):
39+
super().__init__(bidding_model_object,
40+
day_ahead_horizon,
41+
real_time_horizon,
42+
solver,
43+
forecaster)
44+
self.wind_marginal_cost = 0
45+
self.wind_mw = self.bidding_model_object._wind_pmax_mw
46+
self.pem_marginal_cost = pem_marginal_cost
47+
self.pem_mw = pem_mw
48+
49+
def compute_day_ahead_bids(self, date, hour=0):
50+
"""
51+
DA Bid: from 0 MW to (Wind Resource - PEM capacity) MW, bid $0/MWh.
52+
from (Wind Resource - PEM capacity) MW to Wind Resource MW, bid 'pem_marginal_cost'
53+
54+
If Wind resource at some time is less than PEM capacity, then reduce to available resource
55+
"""
56+
gen = self.generator
57+
forecast = self.forecaster.forecast_day_ahead_capacity_factor(date, hour, gen, self.day_ahead_horizon)
58+
59+
full_bids = {}
60+
61+
for t_idx in range(self.day_ahead_horizon):
62+
da_wind = forecast[t_idx] * self.wind_mw
63+
grid_wind = max(0, da_wind - self.pem_mw)
64+
bids = [(0, 0), (grid_wind, 0), (da_wind, self.pem_marginal_cost)]
65+
cost_curve = convert_marginal_costs_to_actual_costs(bids)
66+
67+
temp_curve = {
68+
"data_type": "cost_curve",
69+
"cost_curve_type": "piecewise",
70+
"values": cost_curve,
71+
}
72+
tx_utils.validate_and_clean_cost_curve(
73+
curve=temp_curve,
74+
curve_type="cost_curve",
75+
p_min=0,
76+
p_max=max([p[0] for p in cost_curve]),
77+
gen_name=gen,
78+
t=t_idx,
79+
)
80+
81+
t = t_idx + hour
82+
full_bids[t] = {}
83+
full_bids[t][gen] = {}
84+
full_bids[t][gen]["p_cost"] = cost_curve
85+
full_bids[t][gen]["p_min"] = 0
86+
full_bids[t][gen]["p_max"] = da_wind
87+
full_bids[t][gen]["startup_capacity"] = da_wind
88+
full_bids[t][gen]["shutdown_capacity"] = da_wind
89+
90+
self._record_bids(full_bids, date, hour, Market="Day-ahead")
91+
return full_bids
92+
93+
def compute_real_time_bids(
94+
self, date, hour, _, __
95+
):
96+
"""
97+
RT Bid: from 0 MW to (Wind Resource - PEM capacity) MW, bid $0/MWh.
98+
from (Wind Resource - PEM capacity) MW to Wind Resource MW, bid 'pem_marginal_cost'
99+
100+
If Wind resource at some time is less than PEM capacity, then reduce to available resource
101+
"""
102+
gen = self.generator
103+
forecast = self.forecaster.forecast_real_time_capacity_factor(date, hour, gen, self.day_ahead_horizon)
104+
105+
full_bids = {}
106+
107+
for t_idx in range(self.real_time_horizon):
108+
rt_wind = forecast[t_idx] * self.wind_mw
109+
grid_wind = max(0, rt_wind - self.pem_mw)
110+
bids = [(0, 0), (grid_wind, 0), (rt_wind, self.pem_marginal_cost)]
111+
112+
t = t_idx + hour
113+
full_bids[t] = {}
114+
full_bids[t][gen] = {}
115+
full_bids[t][gen]["p_cost"] = convert_marginal_costs_to_actual_costs(bids)
116+
full_bids[t][gen]["p_min"] = 0
117+
full_bids[t][gen]["p_max"] = rt_wind
118+
full_bids[t][gen]["startup_capacity"] = rt_wind
119+
full_bids[t][gen]["shutdown_capacity"] = rt_wind
120+
121+
self._record_bids(full_bids, date, hour, Market="Real-time")
122+
return full_bids

0 commit comments

Comments
 (0)