-
Notifications
You must be signed in to change notification settings - Fork 235
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
base: main
Are you sure you want to change the base?
Conversation
…-pse into adam-a-a-price-taker-model
… functions to add constraints through pyomo blocks
…y argument for ramping func
@adam-a-a @radhakrishnatg Leaving a comment here so that we remember to discuss next week whether or not the scipy tools will suffice or if we want to go through the hurdle of adding additional dependencies with sklearn (scikit-learn) |
Summarizing the conversation from the dev call:
|
docs/reference_guides/apps/grid_integration/multiperiod/Price_Taker.rst
Outdated
Show resolved
Hide resolved
Builds the 'design model' for a unit/process. | ||
|
||
Args: | ||
model_func: Function that builds the design model | ||
model_args: Dictionary containing the arguments needed for model_func | ||
|
||
The class defines `install_unit` binary variable that takes the value 1 | ||
if the unit is built/installed, and 0 otherwise. | ||
|
||
Function model_func must declare all the necessary design variables, | ||
relations among design variables, capital cost correlations, and fixed O&M | ||
cost correlations. The function must also define attributes `capex` for | ||
capital cost, and `fom` for fixed O&M cost. If not defined, these attributes | ||
will be set to zero. | ||
|
||
Example Usage: | ||
|
||
.. code-block:: python | ||
|
||
def my_design_model(m, p_min, p_max, cost): | ||
m.power = Var() | ||
m.min_capacity = Constraint( | ||
expr=p_min * m.install_unit <= m.power | ||
) | ||
m.max_capacity = Constraint( | ||
expr=m.power <= p_max * m.install_unit | ||
) | ||
|
||
# capex and fom must either be a constant, or Var, or Expression | ||
m.capex = Expression(expr=cost["capex"] * m.power) | ||
m.fom = Expression(expr=cost["fom"] * m.power) | ||
|
||
m = ConcreteModel() | ||
m.unit_1 = DesignModel( | ||
model_func=my_design_model, | ||
model_args={ | ||
"p_min": 150, "p_max": 600, "cost": {"capex": 10, "fom": 1}, | ||
}, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andrewlee94 - documentation for design model
Builds the 'operation model' for a unit/process. | ||
|
||
Args: | ||
model_func: Function that builds the operation model | ||
model_args: Dictionary containing the arguments needed for model_func | ||
|
||
The class defines `op_mode`, `startup`, and `shutdown` binary variables | ||
to track the operation, startup, and shutdown of the unit/process. | ||
|
||
Function model_func must declare all the necessary operation variables, | ||
relations among operation variables, and variable O&M cost correlations. | ||
|
||
Example Usage: | ||
|
||
.. code-block:: python | ||
|
||
def my_operation_model(m, design_blk): | ||
m.power = Var() | ||
m.fuel_flow = Var() | ||
... | ||
|
||
m = ConcreteModel() | ||
m.unit_1 = DesignModel( | ||
model_func=my_design_model, | ||
model_args={ | ||
"p_min": 150, "p_max": 600, "cost": {"capex": 10, "fom": 1}, | ||
}, | ||
) | ||
m.op_unit_1 = OperationModel( | ||
model_func=my_operation_model, model_args={"design_blk": m.unit_1}, | ||
) | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andrewlee94 - documentation for operation model
@andrewlee94 I think we have the basic documentation in here. We also have a tutorial in the pipeline which is pretty much done. Just need approval before putting it up. Thus, maybe that can come in a subsequent PR so that the approval doesn't hold things up further. If there are other spots that are missing documentation, can you highlight any notable gaps? To me, I think this might be ready to merge now, and we can resolve gaps via an issue that tracks those gaps along with subsequent PRs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more requests. The big one is the blanket disabling of pylint warnings - most of those look like things that should actually be fixed, and by doing a blanket disabling I cannot see the lines that are actually causing the issue. This makes it harder to maintain in the future if those issues become sever enough to break the code (these ones are minor enough that they should be fine, but it is a bad habit to get into).
The two other important things are better documenting what happens if the model_func argument is not provided and what this means to the user, and overall documentation of how to actually use these tools to solve a problem (this is probably a subsequent PR).
|
||
# pylint: disable = attribute-defined-outside-init, too-many-ancestors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these necessary? It is generally bad practice to do blanket disabling of pylint warnings, and by doing this I cannot see what was the cause of the warning to suggest how to fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @andrewlee94. My suggestion:
- Remove module-level directives
- Look at the failures and see if it's feasible to address them individually (either by making changes to the code, or using more narrow-scope disable directives)
|
||
if self.config.model_func is None: | ||
# Function that builds the design model is not specified | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the expected behaviour/usage in this case? I note that if this occurs then none of the following code will run, and I do not see any documentation or messages about what this would mean for the user.
I think a logger message is required here at the least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that we should add a logger message here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've addressed this already, but feel free to comment on the warning itself
) | ||
|
||
|
||
@pytest.mark.unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to have more tests of the different edge cases, such as what happens when the user does not provide the function to build the model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added 2 edge cases for when model_func
is not defined in the design or operation model. Perhaps that is enough for now.
Fixes
Compared to #1201, operational constraints mathematical form was corrected. Unnecessary functions were removed/merged. Additional user flexibility was added for constructing cost objectives.
Summary/Motivation:
Resurrecting #1201 to finish price taker framework in accordance with project milestones.
Framework allows the user to construct price-taker models for design and/or operational optimization considering time-varying market price data.
Legal Acknowledgement
By contributing to this software project, I agree to the following terms and conditions for my contribution: