Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Price taker model for DISPATCHES, Rehashed #1358

Open
wants to merge 129 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 126 commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
a3d688c
Added basic price-taker framework
radhakrishnatg May 26, 2023
67ce6a2
run black
adam-a-a Jun 8, 2023
e716c36
add in get_optimal_n_clusters as separate method. hand off to Marcus
adam-a-a Jun 8, 2023
e3788fb
Add methods for computing the optimal # of clusters and making an elb…
MarcusHolly Jun 9, 2023
8ef54be
Merge branch 'main' into adam-a-a-price-taker-model
MarcusHolly Jun 9, 2023
f154700
Merge branch 'main' into price-taker-model
lbianchi-lbl Jun 10, 2023
422d0ba
add fom to typos.toml in github/workflows to pass spellcheck
adam-a-a Jun 12, 2023
2f36bbb
fix typo
adam-a-a Jun 12, 2023
0aa1034
Add tests for new functions (excel import failing)
MarcusHolly Jun 13, 2023
9042e5c
Update dependencies
MarcusHolly Jun 13, 2023
5549028
Merge branch 'price-taker-model' of https://github.com/adam-a-a/idaes…
MarcusHolly Jun 13, 2023
2fde47f
Add pytest marks
MarcusHolly Jun 13, 2023
d0a6c13
Fix typo where TimeStep data was being used instead of BaseCaseTax
MarcusHolly Jun 15, 2023
e5f6c07
Update test file
MarcusHolly Jun 15, 2023
56d9369
Add warning for when kmax is not set
MarcusHolly Jun 15, 2023
9b5edd4
Address Radha's comments and start adding testing (WIP)
MarcusHolly Jun 21, 2023
948f40c
Add more tests
MarcusHolly Jun 22, 2023
30fed63
Add cluster_lmp_data function
MarcusHolly Jun 22, 2023
fc43a3f
linearizing su_sd cosntraints and fixing the price traker model
Aug 3, 2023
4170501
Removing files that were mistakenly saved on this branch
Aug 3, 2023
1d87aea
modified startup and shutdown constraint function
Aug 11, 2023
4710a10
add set_period to startup and shutdown func
Aug 11, 2023
be68154
developed a function to add startup/shutdown constraints
Aug 18, 2023
66db0d8
Constructed a function that adds startup and shutdown constraints
Aug 22, 2023
b39f4d9
Added deepgetattr function and had the ramp-up/down and start-up/down…
Aug 30, 2023
799ed0b
linearized ramping constraints
Sep 14, 2023
7625d07
Added auxiliary variables
Sep 14, 2023
0c2c461
added a third mccor constraint for each aux var and created a capacit…
Sep 18, 2023
16710a6
changed startup_shutdown constraints to have the shutdown binary var
Sep 19, 2023
4518240
changed rule for min_start_up constraint
Sep 19, 2023
35ddead
fixed startup_shutdown function constraints, changed default values f…
Sep 20, 2023
fd15af9
added new method for adding aux variables
Sep 21, 2023
b84ea43
removed aux variable delcaration and added a new config option to opt…
Sep 21, 2023
15ea641
added comments
Sep 21, 2023
53e427e
small addition
Sep 21, 2023
14ee544
added design_blk
Sep 21, 2023
4e10801
added deepgetattr and constraint for the add capacity aux var func
Sep 21, 2023
d68d8fd
finished the new method and ramping function
Sep 22, 2023
6cd966e
Allowed _add_capacity_aux_vars to be cosntructed when the build func…
Oct 4, 2023
f7e3245
added a for loop that calls on the _add_capacity_aux_vars function t …
Oct 4, 2023
b223cf6
Pulling Tyler\'s brnach
Oct 31, 2023
56f8099
Updating PT model for SOFC case study
Nov 1, 2023
48d4d98
Updated price_taker_model.py doc
djlaky Feb 15, 2024
fde3f31
Updated init of PriceTakerModel
djlaky Feb 15, 2024
5bd0d5b
Added missing documentation
djlaky Feb 15, 2024
0df8b45
Corrected constraint expressions
djlaky Feb 15, 2024
fd595b4
Added tests for input checking
djlaky Feb 15, 2024
a54c3ac
Updated checks for get_optimal_clusters
djlaky Feb 15, 2024
70cbaba
Fixed typos in test_price_taker.py
djlaky Feb 15, 2024
85b7bd0
Added input checks on add_ramping_constraints
djlaky Feb 15, 2024
9851b88
Fixed broken test
djlaky Feb 15, 2024
6ede14e
Added automated LMP population
djlaky Feb 16, 2024
d31b272
Fixed getitem issues with Sets
djlaky Feb 16, 2024
769ba7b
Removed redundant set definition
djlaky Feb 16, 2024
0bba4d2
Added n_clusters check in append_lmp_data
djlaky Feb 16, 2024
b06d467
Reorganizing unit logging messages tests
djlaky Feb 20, 2024
0cf82bf
Moved deepgetattr to import from design_and_operation_models.py
djlaky Feb 21, 2024
6af8c9e
Added checks and tests
djlaky Feb 21, 2024
1fc5f53
Updated data processing workflow
djlaky Feb 22, 2024
e991392
Small update to append_lmp_data
djlaky Feb 22, 2024
f2725cc
Updated get_optimal_n_clusters
djlaky Feb 27, 2024
522023b
Updated cash flow construction
djlaky Feb 27, 2024
22dbe12
Added tests for cashflows
djlaky Feb 27, 2024
6dbb183
Fixed typos and ran black
djlaky Feb 29, 2024
7a86d03
Run black
djlaky Feb 29, 2024
7a24fba
Fixed some broken tests
djlaky Feb 29, 2024
b1629eb
Removed a test that is failing
djlaky Feb 29, 2024
d193e65
Reverted pytests.ini and corrected tests
djlaky Mar 4, 2024
fb543c7
Updated plotting test
djlaky Mar 4, 2024
460af99
Ran Black again
djlaky Mar 4, 2024
c90bbe1
Merge branch 'IDAES:main' into price-taker-model
djlaky Mar 4, 2024
643707f
Updating tests
djlaky Mar 5, 2024
8aa02c6
Add capacity limits function
djlaky Mar 25, 2024
323e4a9
Added final docstring
djlaky Mar 25, 2024
04d07ae
Ran black
djlaky Mar 25, 2024
4ae5779
Bugfix capacity constraints
djlaky Mar 25, 2024
893743d
Removed multiyear LMP support
djlaky Mar 27, 2024
82f8bdc
Merge branch 'IDAES:main' into price-taker-model
djlaky Mar 27, 2024
ebdc1b2
Delete idaes/apps/grid_integration/multiperiod/ERCOT_WEST_2022_shutdo…
djlaky Mar 28, 2024
aad41fb
Update docstring for n_clusters
djlaky Apr 30, 2024
e2dac86
Fixed typos.
djlaky Apr 30, 2024
5ad727e
Removed design_blk as an input for Operation_Model
djlaky Apr 30, 2024
2ae4635
Fixed typo in error message in tests
djlaky Apr 30, 2024
8762f7b
Replace deepgetattr with find_component()
djlaky Apr 30, 2024
7110dea
Changed dependence of tests on .xlsx to .csv
djlaky Apr 30, 2024
8550569
Merge branch 'IDAES:main' into price-taker-model
djlaky Apr 30, 2024
69c3c9b
Changed deepgetattr functionality to find_component
djlaky Apr 30, 2024
177618c
Merge branch 'price-taker-model' of https://github.com/dlakes94/idaes…
djlaky Apr 30, 2024
ce4b0fb
Updated test to remove .xlsx dependencies
djlaky Apr 30, 2024
343d191
Update on build_hourly_cashflows docstring
djlaky Apr 30, 2024
cec302e
Update for Sphinx again
djlaky Apr 30, 2024
652d1cc
Ran black
djlaky Apr 30, 2024
d8ade5d
Updated SkeletonUnitModelData to ProcessBlockData
djlaky May 8, 2024
cd3f3d3
Made sklearn and kneed optional, added log msgs
djlaky May 8, 2024
ce6b3db
Updated tests for price taker class
djlaky May 8, 2024
f4cfbdb
Fixed optional import tests
djlaky May 8, 2024
cbd7aaa
Ran black
djlaky May 8, 2024
f10ea59
Bugfix kmeans for LMP
djlaky May 16, 2024
46a3331
merged idaes main
May 29, 2024
7bdd94d
Revert "merged idaes main"
djlaky Jun 10, 2024
1c85981
Add initial documentation for pricetaker
MarcusHolly Jul 12, 2024
6956d73
Add autoclass to documentation
MarcusHolly Jul 12, 2024
8b4b479
Address merge conflict
MarcusHolly Jul 12, 2024
646b88b
Fix typos in documentation
MarcusHolly Jul 12, 2024
a1f1eb2
Reformat how math equations are handled
MarcusHolly Jul 12, 2024
8101448
add subtle additions to price-taker model used in workhop
adam-a-a Jul 15, 2024
d8de0dd
Merge branch 'main' into price-taker-model
adam-a-a Jul 23, 2024
fc7369e
Test for seed instance and seed ValueError
MarcusHolly Sep 5, 2024
75a56f4
Check for expected string outputs rather than using f-strings
MarcusHolly Sep 5, 2024
df687af
Separate tests that check for multiple error messages
MarcusHolly Sep 5, 2024
47b66c5
Separate a majority of the code outside of the pytest.raises
MarcusHolly Sep 6, 2024
8ac5987
Update imports
MarcusHolly Sep 9, 2024
d10b9a7
Merge branch 'main' into price-taker-model
MarcusHolly Sep 9, 2024
1e7842a
Add version check for sklearn
MarcusHolly Sep 9, 2024
8b1393a
Add separate function & test for generating elbow plots
MarcusHolly Sep 9, 2024
6481545
Refines version testing and # of optimal clusters testing
MarcusHolly Sep 11, 2024
b9f3ef4
Remove unused imports
MarcusHolly Sep 11, 2024
bd2db6f
Merge branch 'price-taker-model' of https://github.com/djlaky/idaes-p…
MarcusHolly Sep 11, 2024
9cf4a3a
Merge branch 'main' into djlaky-price-taker-model
MarcusHolly Oct 15, 2024
112761f
Correct acronym in pricetaker documentation
MarcusHolly Oct 15, 2024
fb0a05b
Remove commented code in design_and_operation_models
MarcusHolly Oct 15, 2024
5d960a4
Add dependencies for scikit-learn and kneed
MarcusHolly Oct 15, 2024
d7a0002
Update imports and seed.setter method
MarcusHolly Oct 15, 2024
727be78
Resolve test failures
MarcusHolly Oct 16, 2024
aebe5b8
Update pricetaker to not create new dependencies
MarcusHolly Oct 17, 2024
411bb60
Update pricetaker testing based on previous commit
MarcusHolly Oct 17, 2024
bd3244c
Refine docstring for compute_sse method
MarcusHolly Oct 17, 2024
b8149b5
Make compute_sse a prviate method & move outside of class
MarcusHolly Oct 17, 2024
043ac34
Update compute_sse docstring
MarcusHolly Oct 17, 2024
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
3 changes: 3 additions & 0 deletions .github/workflows/typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ equil = "equil"
astroid = "astroid"
# delt == delta
delt = "delt"
# FOM for fixed operating and maintenance for DISPATCHES
FOM = "FOM"
fom = "fom"
# Minimal Infeasible System
mis = "mis"
MIS = "MIS"
Expand Down
1 change: 1 addition & 0 deletions docs/reference_guides/apps/grid_integration/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ wholesale electricity markets. For more information, please look at the introduc
Bidder
Tracker
Coordinator
multiperiod/index

Cite us
^^^^^^^
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Price Taker
===========

Price takers are companies or individuals who must accept market prices since they lack the market share
to directly influence the market price. Likewise, it is assumed that a price taker's resource or energy
system is small enough such that it does not significantly impact the market. When coupled with multi-period modeling,
the price-taker model is able to synthesize grid-centric modeling with steady-state process-centric modeling, as
depicted in figure below.

.. |pricetaker| image:: images/pricetaker.png
:width: 1200
:alt: Alternative text
:align: middle

|pricetaker|

The following equations represent the multi-period price taker model, where :math:`d` are design decisions,
:math:`u` are operating decisions, :math:`δ` are power decisions, :math:`s` are scenarios (timeseries/representative days),
:math:`w` is weight/frequency, :math:`R` is revenue, :math:`π` is price data,
:math:`C` is capital and operating costs, :math:`g` is the process model, and :math:`h` is the temporal constraint.

.. math::

max_{d,u, δ} = \sum_{s ∈ S} \sum_{t ∈ T} w_{s}[R(d,u_{s,t},δ_{s,t},π_{s,t}) - C(d,u_{s,t},δ_{s,t})]

.. math::

g(d,u_{s,t},δ_{s,t}) = 0; ∀_{s} ∈ S, t ∈ T

.. math::

h(d,u_{s,t},δ_{s,t},u_{s,t+1},δ_{s,t+1}) = 0; ∀_{s} ∈ S, t ∈ T


The price taker multi-period modeling workflow involves the integration of multiple software platforms into the IDAES optimization model
and can be broken down into two distinct functions, as shown in the figure below. In part 1, simulated or historical
ISO (Independent System Operator) data is used to generate locational marginal price (LMP)
signals, and production cost models (PCMs) are used to compute and optimize the time-varying dispatch schedules for each
resource based on their respective bid curves. Advanced data analytics (RAVEN) reinterpret the LMP signals and PCM
as stochastic realizations of the LMPs in the form of representative days (or simply the full-year price signals).
In part 2, PRESCIENT uses a variety of input parameters (design capacity, minimum power output, ramp rate, minimum up/down time, marginal cost, no load cost, and startup profile)
to generate data for the market surrogates. Meanwhile, IDAES uses the double loop simulation to integrate detailed
process models (b, ii) into the daily (a, c) and hourly (i, iii) grid operations workflow.

.. |hybrid_energy_system| image:: images/hybrid_energy_system.png
:width: 1200
:alt: Alternative text
:align: middle

|hybrid_energy_system|

.. module:: idaes.apps.grid_integration.multiperiod.price_taker_model

.. autoclass:: PriceTakerModel
:members:
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Multi-Period Modeling
=====================

Multi-period modeling can be used to simplify dynamic optimization problems
by linking steady-state models over a time horizon with rate-limiting constraints.
Therefore, sets of constraints at one temporal index will affect decisions taken
at a different moment in time. These interactions can be used to model the relationship
between the energy systems and wholesale electricity markets.

.. toctree::
:maxdepth: 2

Price_Taker
5 changes: 5 additions & 0 deletions idaes/apps/grid_integration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@
from .coordinator import DoubleLoopCoordinator
from .forecaster import PlaceHolderForecaster
from .multiperiod.multiperiod import MultiPeriodModel
from .multiperiod.price_taker_model import PriceTakerModel
from .multiperiod.design_and_operation_models import (
DesignModel,
OperationModel,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#################################################################################
# The Institute for the Design of Advanced Energy Systems Integrated Platform
# Framework (IDAES IP) was produced under the DOE Institute for the
# Design of Advanced Energy Systems (IDAES).
#
# Copyright (c) 2018-2023 by the software owners: The Regents of the
# University of California, through Lawrence Berkeley National Laboratory,
# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon
# University, West Virginia University Research Corporation, et al.
# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md
# for full copyright and license information.
#################################################################################
from functools import reduce
from pyomo.environ import (
Var,
Param,
Binary,
Expression,
NonNegativeReals,
Constraint,
)
from pyomo.common.config import ConfigValue, In
from idaes.core.base.process_base import declare_process_block_class
from idaes.core.base.process_base import ProcessBlockData


@declare_process_block_class("DesignModel")
class DesignModelData(ProcessBlockData):
"""
Class for containing design model ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still do not know enough about what this class actually does to approve this. The docs do not explain what this is or how to use it, and I am not sure what this code actually adds (i.e. is it even necessary?).

For one, this needs a descriptive doc string to explain what it does.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@radhakrishnatg would be the best person to respond to this.

"""

CONFIG = ProcessBlockData.CONFIG()
CONFIG.declare(
"model_func",
ConfigValue(
doc="Function that builds the design model",
),
)
CONFIG.declare(
"model_args",
ConfigValue(
default={},
doc="Dictionary containing arguments needed for model_func",
),
)

def build(self):
super().build()

self.config.model_func(self, **self.config.model_args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a little odd to me - what exactly is the purpose of this class and function? As best I can tell, it appears to be a wrapper that lets a user write the build function alone and then put it into an IDAES ProcessBlock. If this is the case, is this really necessary, as it adds an extra layer of abstraction and possible confusion for the user (and something else we need to test)? Also, this would need to be clearly documented for the user.



@declare_process_block_class("OperationModel")
class OperationModelData(ProcessBlockData):
"""
Class for containing design model ...
"""

CONFIG = ProcessBlockData.CONFIG()
CONFIG.declare(
"model_func",
ConfigValue(
doc="Function that builds the design model",
),
)
CONFIG.declare(
"model_args",
ConfigValue(
default={},
doc="Dictionary containing arguments needed for model_func",
),
)

CONFIG.declare(
"declare_op_vars",
ConfigValue(
default=True,
domain=In([True, False]),
doc="Should op_mode, startup, shutdown vars be defined?",
),
)
CONFIG.declare(
"append_lmp_data",
ConfigValue(
default=True,
domain=In([True, False]),
doc="Should LMP data automatically be appended to the model?",
),
)

# noinspection PyAttributeOutsideInit
def build(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, the usage of this class will need to be clearly documented, especially what model_func is expected to do. I am again wondering if it would be better to get the user to inherit from this and just write model_func as their build method.

super().build()

# Build the model
if self.config.declare_op_vars:
self.op_mode = Var(
within=Binary,
doc="Binary var: 1 if the unit is operating, 0 otherwise",
)

self.startup = Var(
within=Binary,
doc="Binary var: 1 if the startup is initiated, 0 otherwise",
)

self.shutdown = Var(
within=Binary,
doc="Binary var: 1 if the shutdown is initiated, 0 otherwise",
)

if self.config.append_lmp_data:
self.LMP = Param(
initialize=1,
mutable=True,
doc="Parameter: Will be updated to LMP value at given time",
)

self.config.model_func(self, **self.config.model_args)
radhakrishnatg marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading