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 140 commits into
base: main
Choose a base branch
from

Conversation

djlaky
Copy link

@djlaky djlaky commented Feb 29, 2024

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:

  1. I agree my contributions are submitted under the license terms described in the LICENSE.txt file at the top level of this directory.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

radhakrishnatg and others added 30 commits May 25, 2023 21:46
… functions to add constraints through pyomo blocks
@MarcusHolly
Copy link
Contributor

@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)

@lbianchi-lbl
Copy link
Contributor

Summarizing the conversation from the dev call:

  • Authors and reviewers seem to agree that the clustering methods available through SciPy are sufficient for the current needs
  • Therefore, this PR should not add any new dependencies; authors can go ahead and remove/undo the corresponding code changes (attempt_import, etc) from this PR
  • Different clustering strategies and/or implementations can be added in a future PR once this has been merged

Comment on lines +28 to +66
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},
},
)
Copy link
Contributor

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

Comment on lines +118 to +149
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},
)
"""
Copy link
Contributor

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

@adam-a-a
Copy link
Contributor

adam-a-a commented Nov 4, 2024

@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.

Copy link
Member

@andrewlee94 andrewlee94 left a 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
Copy link
Member

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.

Copy link
Contributor

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
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Contributor

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
Copy link
Member

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.

Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DISPATCHES Priority:Normal Normal Priority Issue or PR WaterTAP
Projects
None yet
Development

Successfully merging this pull request may close these issues.