-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into updates_idaes
- Loading branch information
Showing
51 changed files
with
38,366 additions
and
45,481 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Renewable Energy Case Study: Wind + PEM and Wind + Battery Plants | ||
|
||
This directory contains the files required for the renewable energy case studies, which use flowsheets in which any of the following | ||
technologies (modeled as unit models) may be present: Wind, PV, Battery, PEM Electrolysis, Hydrogen Storage Tank and Hydrogen Turbine. | ||
The RE case studies focused on a Wind + PEM plant and a Wind + Battery plant, while the the industry-partnership case study looked at a PV + Battery + PEM + Hydrogen. | ||
Each of these three case studies has different approaches to modeling prices or the grid. | ||
|
||
## Wind + PEM case: | ||
|
||
1. Price-taker Design Optimization: `dispatches/case_studies/renewables_case/run_pricetaker_wind_PEM.py` | ||
2. Market Surrogate Design Optimization: `dispatches/case_studies/renewables_case/RE_surrogate_optimization_steadystate.py` | ||
3. Double Loop Simulation for Validation: `dispatches/case_studies/renewables_case/run_double_loop_PEM.py` | ||
4. Market Surrogate Design and Validation Plotting: `dispatches/case_studies/renewables_case/SurrogateDesignResults.ipynb` | ||
|
||
## Wind + Battery case: | ||
1. Price-taker Design Optimization: `dispatches/case_studies/renewables_case/run_pricetaker_battery_ratio_size.py` | ||
2. Double Loop Simulation: `dispatches/case_studies/renewables_case/run_double_loop_battery.py` | ||
3. Parametrized Bidder Double Loop Simulation: `dispatches/case_studies/renewables_case/run_double_loop_battery_parametrized.py` | ||
|
||
## PV + Battery + Hydrogen case: | ||
1. Price-taker Design Optimization: `dispatches/case_studies/renewables_case/solar_battery_hydrogen.py` | ||
|
||
## Software and Hardware | ||
All the models are run on a Red Hat Enterprise Linux Server version 7.9 (Maipo). The versions for the solvers used are given below: | ||
- Xpress: Version 8.13.0 | ||
- IPOPT: Version 3.13.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,593 changes: 933 additions & 660 deletions
1,593
dispatches/case_studies/renewables_case/SurrogateDesignResults.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
124 changes: 124 additions & 0 deletions
124
dispatches/case_studies/renewables_case/battery_parametrized_bidder.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
################################################################################# | ||
# DISPATCHES was produced under the DOE Design Integration and Synthesis Platform | ||
# to Advance Tightly Coupled Hybrid Energy Systems program (DISPATCHES), and is | ||
# copyright (c) 2020-2023 by the software owners: The Regents of the University | ||
# of California, through Lawrence Berkeley National Laboratory, National | ||
# Technology & Engineering Solutions of Sandia, LLC, Alliance for Sustainable | ||
# Energy, LLC, Battelle Energy Alliance, LLC, University of Notre Dame du Lac, et | ||
# al. All rights reserved. | ||
# | ||
# Please see the files COPYRIGHT.md and LICENSE.md for full copyright and license | ||
# information, respectively. Both files are also available online at the URL: | ||
# "https://github.com/gmlc-dispatches/dispatches". | ||
################################################################################# | ||
import numpy as np | ||
from idaes.apps.grid_integration.bidder import convert_marginal_costs_to_actual_costs, tx_utils | ||
from dispatches.workflow.parametrized_bidder import ParametrizedBidder | ||
|
||
|
||
class FixedParametrizedBidder(ParametrizedBidder): | ||
|
||
""" | ||
Template class for bidders that use fixed parameters. | ||
The functions for computing the day ahead and real time bids do not use any information from Prescient, | ||
and only depend on internal system information such as wind capacity factors, and on bid parameters. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
bidding_model_object, | ||
day_ahead_horizon, | ||
real_time_horizon, | ||
solver, | ||
forecaster, | ||
storage_marginal_cost, | ||
storage_mw | ||
): | ||
super().__init__(bidding_model_object, | ||
day_ahead_horizon, | ||
real_time_horizon, | ||
solver, | ||
forecaster) | ||
self.wind_marginal_cost = 0 | ||
self.wind_mw = self.bidding_model_object._wind_pmax_mw | ||
self.storage_marginal_cost = storage_marginal_cost | ||
self.storage_mw = storage_mw | ||
|
||
def compute_day_ahead_bids(self, date, hour=0): | ||
""" | ||
Day ahead bid has two parts: | ||
1. the part of the DA wind energy that is able to be stored in the battery is at the higher "storage_marginal_cost" | ||
2. the remainder of the wind energy is bid at the wind marginal cost of $0/MWh | ||
For each time period in the day ahead horizon, the marginal cost bid is assembled as the two parts. | ||
Then the marginal costs are converted to actual costs, as expected by Prescient. | ||
""" | ||
gen = self.generator | ||
forecast = self.forecaster.forecast_day_ahead_capacity_factor(date, hour, gen, self.day_ahead_horizon) | ||
|
||
full_bids = {} | ||
|
||
for t_idx in range(self.day_ahead_horizon): | ||
da_wind = forecast[t_idx] * self.wind_mw | ||
p_max = max(da_wind, self.storage_mw) | ||
bids = [(0, 0), (max(0, da_wind - self.storage_mw), 0), (p_max, self.storage_marginal_cost)] | ||
cost_curve = convert_marginal_costs_to_actual_costs(bids) | ||
|
||
temp_curve = { | ||
"data_type": "cost_curve", | ||
"cost_curve_type": "piecewise", | ||
"values": cost_curve, | ||
} | ||
tx_utils.validate_and_clean_cost_curve( | ||
curve=temp_curve, | ||
curve_type="cost_curve", | ||
p_min=0, | ||
p_max=max([p[0] for p in cost_curve]), | ||
gen_name=gen, | ||
t=t_idx, | ||
) | ||
|
||
t = t_idx + hour | ||
full_bids[t] = {} | ||
full_bids[t][gen] = {} | ||
full_bids[t][gen]["p_cost"] = cost_curve | ||
full_bids[t][gen]["p_min"] = 0 | ||
full_bids[t][gen]["p_max"] = p_max | ||
full_bids[t][gen]["startup_capacity"] = p_max | ||
full_bids[t][gen]["shutdown_capacity"] = p_max | ||
|
||
self._record_bids(full_bids, date, hour, Market="Day-ahead") | ||
return full_bids | ||
|
||
def compute_real_time_bids( | ||
self, date, hour, realized_day_ahead_prices, realized_day_ahead_dispatches | ||
): | ||
""" | ||
Real time bid has two parts: | ||
1. the part of the RT wind energy that is able to be stored in the battery is at the higher "storage_marginal_cost" | ||
2. the remainder of the wind energy is bid at the wind marginal cost of $0/MWh | ||
For each time period in the day ahead horizon, the marginal cost bid is assembled as the two parts. | ||
Then the marginal costs are converted to actual costs, as expected by Prescient. | ||
""" | ||
gen = self.generator | ||
forecast = self.forecaster.forecast_real_time_capacity_factor(date, hour, gen, self.day_ahead_horizon) | ||
|
||
full_bids = {} | ||
|
||
for t_idx in range(self.real_time_horizon): | ||
rt_wind = forecast[t_idx] * self.wind_mw | ||
p_max = max(rt_wind, self.storage_mw) | ||
bids = [(0, 0), (max(0, rt_wind - self.storage_mw), 0), (p_max, self.storage_marginal_cost)] | ||
|
||
t = t_idx + hour | ||
full_bids[t] = {} | ||
full_bids[t][gen] = {} | ||
full_bids[t][gen]["p_cost"] = convert_marginal_costs_to_actual_costs(bids) | ||
full_bids[t][gen]["p_min"] = 0 | ||
full_bids[t][gen]["p_max"] = p_max | ||
full_bids[t][gen]["startup_capacity"] = p_max | ||
full_bids[t][gen]["shutdown_capacity"] = p_max | ||
|
||
self._record_bids(full_bids, date, hour, Market="Real-time") | ||
return full_bids |
Binary file added
BIN
+199 KB
dispatches/case_studies/renewables_case/data/303_LMPs_15_reserve_1000_shortfall.parquet
Binary file not shown.
Binary file added
BIN
+205 KB
dispatches/case_studies/renewables_case/data/303_LMPs_15_reserve_500_shortfall.parquet
Binary file not shown.
Oops, something went wrong.