-
Notifications
You must be signed in to change notification settings - Fork 134
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
Add nonconvex investment flow #826
Add nonconvex investment flow #826
Conversation
* :math: `new_param(i,o,t)` (non-negative real number) | ||
new paramater representing the multiplication of | ||
`P_{invest}` and status(i,o,t)`used for the constraints | ||
on the minimum and maximum flow constraints. |
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 about P_{status}
?
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 about
P_{status}
?
I think P_{status}
is NOT required here. It is already used in rule definitions for minimum and maximum investment and also in the objective function.
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 wanted to suggest to (re)name the parameter new_param
(to) P_{status}
. As it is the product of the nominal power and the status, the name would make sense, imho.
Hi @sasa821, thanks for your contribution. As far as I see, the code does what it is supposed to do. To be included in the release, unit tests should be included. (Note that the test fails that checks for the error message when combining In my opinion, the complexity (cf. Codacy check) is okay. Also, you introduce some code duplication. Both is supposed to be cleaned up later. (We currently have more duplication then necessary, it should not be hard to address the newly induced duplication when we fix the existing one.) |
How about naming it |
Hi @p-snft, thank you very much for your review. Could you assist me more with the inclusion of unit tests, please? |
Thanks, @joroeder, for your comment. I used the name |
I'd be glad to help you. However, I am currently lacking time, so it will take some weeks until I can do so. |
@sasa821: I'd have time now. Thus, I read through the full PR as it is right now. As using this module is restricted to special solvers, testing will be difficult. Also, I am considering if we should add a warning to the init function, so that nobody uses the feature with an unsupported solver. |
@p-snft - I just tested it with cbc and it works, I am not sure I understand your point here? |
@sasa821 stated that
I just believed that without testing it myself. As you say it works, I will test it. |
@p-snft I also wanted to ask if it would be ok to rebase the PR onto the latest state of |
@p-snft: I meant that the linearization of the multiplication of a binary and a continuous variable is automatically done in Gurobi, but in cbc this is not the case. Therefore, I added 3 additional constraints to make it possible for cbc to solve the problem. So, the new class is NOT restricted to a specific solver. |
7981b92
to
e2e11af
Compare
I just opened a PR to your branch (@sasa821 ) with two examples for combinations of Invest/NonConvex. I did this just to have something at hand to test if the class works technically. (It does, thank you!) It would be nice if you could provide an example that reproduces the two plots you show in the first post of this PR. After that, the next step would be adding the tests. Typically, the examples are a good starting points to create tests. This is why I contributed one for |
Thanks @p-snft - So examples are providable within oemof-solph package? I thought one had to store them in the oemof-examples repository (this is the reason why I told @sasa821 we should not commit his example file). Can one add tests where a simulation is run and we look at its output? We already added/modified a few tests in this PR, I am not sure if there is a "good" number of tests to be added ? |
We used to have them separately. But as there are severe drawbacks (i.e. results are not tested automatically), this is about to change with v0.5. When it comes to tests, of course the examples will be checked. This, however, is rather an integration test than a unit test. Thus, we need to add tests for individual functionality. In particular, there should be a constraint test that checks the generated LP file. |
@p-snft - @sasa821 and I plan to wrap up this PR (the work being done now is on the integration and constraint tests, as well as modifying the documentation to have this feature explined) this coming wednesday would you be able/available to review it then? If not could you suggest another core dev of oemof? |
docs/usage.rst
Outdated
Solph also allows you to model components with respect to more technical details, | ||
such as minimum power production. This can be done in two different modes: | ||
dispatch optimization with fixed capacities and combined dispatch and investment optimization. |
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.
As you now allow combining investments and non-convex operation, the "modes" might be confusing. Maybe, tell that we offer different kinds of Flows with different capabilities to increase the computational performance of the model. It's always
(Actually, they were confusing before. Many people though that you could not have NonConvexFlow
s in an invest optimisation. However, it always worked as long as you do not want to invest in that particular flow.)
I'd gladly do that. I can also offer to not consider problem with docs for solph as a whole (in the sense of #826 (review)) as blockers. Instead, we will rewrite those later. PS: To be named when the code is cited in scientific publications, you should add your names to https://github.com/oemof/oemof-solph/blob/dev/CITATION.cff. (It was not mentioned in the contribution guidelines, I just fixed that.) |
f7b67d9
to
daebfa4
Compare
|
||
Installation requirements | ||
------------------------- | ||
This example requires the version v0.5.x of oemof. Install by: |
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.
This example requires the version v0.5.x of oemof. Install by: | |
This example requires the version v0.5.x of oemof.solph. Install by: |
(I know, my fault.)
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.
Done in 3f55df9
initial_status=0, | ||
positive_gradient=None, | ||
negative_gradient=None, | ||
**kwargs, |
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.
Just a note, as your PR aligns with the old/current practice: We want to get rid of "**kwargs". This i.e. will catch typos. The v0.5 way to go is to explicitly define all keyword arguments.
However, you should not expose the "Investment" option as you already did the step to hide the "NonConvex" option. Instead, allow an (explicit) option ep_costs
. (It's clear that there is an investment from the choice of the class.)
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.
As NonConvexInvestmentFlow
inherits from Flow
and Flow
itself uses **kwargs
, we then might as well define explicitely the argument in Flow
, no? Couldn't this be tackled in a separate PR?
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 understand the benefit of explicit by getting rid of **kwargs
, however wouldn't it make maintenance of inherited classes more cumbersome ? Moreover if typos are caught, then errors in the default values of the arguments in a child class are not caught (a solution for that would be to only pass the argument to the parent class if they don't have the default value of the child class, that way only the default value of the parent class rules.)
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.
You are right, this can be done separately, as the Flow is not updated yet.
(Maybe, this PR is not the right place to discuss about the pros and cons of **kwags. We came to the conclusion to user friendlyness is the stronger argument in the current state of the package. So, all expected arguments are now made explicit. If you want additional arguments, you can still use them, but you have to hand them as a dict to the argument "options".)
tests/test_scripts/test_solph/test_nonconvex_investment/test_nonconvex_investment.py
Outdated
Show resolved
Hide resolved
class FlowOptionWarning(UserWarning): | ||
pass | ||
|
||
|
||
class WrongOptionCombinationError(ValueError): | ||
pass |
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.
We have the other warnings in the tools package, to allow reusing them. It might make sense to do this for these exceptions as well.
(Just as a point for discussion, not a reason to reject this PR.)
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 only saw one other warning SuspiciousUsageWarning
in oemof.tools
. We could define them there if this is needed. I personally find a bit cumbersome to have to create 2 PRs in 2 different packages, but I will abide :)
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.
Maybe, we should also get rid of the SuspiciousUsageWarning
in tools... I just brought this up so that the point can be considered in discussions about the overall structure of the oemof packages. (We have a lot of open discussion.)
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.
As this would then be a minor change to move them to oemof.tools
or to move SuspiciousUsageWarning
in _exceptions.py
, could we leave it as is for now and act when the open discussion comes to a conclusion :) ?
Describe the change introduced by the NonConvexInvestFlow Co-authored-by: sasa821 <83787088+sasa821@users.noreply.github.com>
Co-authored-by: sasa821 <83787088+sasa821@users.noreply.github.com>
Co-authored-by: sasa821 <83787088+sasa821@users.noreply.github.com>
Co-authored-by: sasa821 <83787088+sasa821@users.noreply.github.com>
Since the new parameter `invest_non_convex` exists in the `NonConvexInvestFlow`, there is no need for the `invest_status`. Moreover, usage of the `NonConvexInvestFlow` class indicates that the `invest` always exists. Therefore, `invest_status` can be removed and by removing it, the computation time would increase. Co-Authored-By: Pierre Francois <4399407+Bachibouzouk@users.noreply.github.com>
The sets `NON_FIXED_INVESTFLOWS` and `FIXED_INVESTFLOWS` and their corresponding constraints are removed because they seem to be unnecessary in the `NonConvexInvestFlow` and removing them would increase the computation time. Co-Authored-By: Pierre Francois <4399407+Bachibouzouk@users.noreply.github.com>
Change the `min`, `max`, and `conversion_factors` values to numbers that can be cast from decimal to floating-point and back (e.g., 0.25, 0.5, ...) to increase the readability of the corresponding *.lp file. Co-Authored-By: Pierre Francois <4399407+Bachibouzouk@users.noreply.github.com>
Explicitly name authors in the "SPDX-FileCopyrightText". Co-Authored-By: Pierre Francois <4399407+Bachibouzouk@users.noreply.github.com>
In some parts, the name of the `NonConvexInvestFlow` was written incorrectly. Co-Authored-By: Pierre Francois <4399407+Bachibouzouk@users.noreply.github.com>
Modify the example file because it is not read from somewhere else. Co-Authored-By: Pierre Francois <4399407+Bachibouzouk@users.noreply.github.com>
Co-authored-by: sasa821 <83787088+sasa821@users.noreply.github.com>
2dec8cf
to
cc747bd
Compare
@p-snft - we implemented the changes you suggested, with exception of the parts we agreed could be tackled in subsequent PRs. There is also need to approve running the workflows of the PR |
I hat to reopened the v0.5 branch to be able to reopen this PR. Afterwards, I could rebase it. Done. PS: I do not use a github address for my contributions. I'm fine with the address in the commit log. |
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.
In my opinion, the remaining issues have to be solved rather in the original solph Flows then in this PR.
- Documentation of the Flow classes: I.e. the non-convex "mode" and investment "mode" don't really exist since there is NonconvexFlow and InvestmentFlow.
- Code duplication: The flow classes should be more modular. But this is nothing to be fixed here.
- Test coverage: There are missing tests for duplicated code. This will solve as soon as the duplication is removed by making the original flow more modular.
So, I'd agree to merge this. (If a second reviewer has a problem with temporarily decreasing test coverage, moving the NonConvexInvestmentFlow into a subdirectory called "experimental" might help. We do the same thing for components.)
Thanks @p-snft, now the target branch is correct, should someone else review this PR? Or merge it? |
I asked for a second reveiw in the dev chat. For non-trivial stuff we want to have more then one review if possible. |
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.
First of all, I think that is really nice contribution. Thanks to all people that were involved.
I would appreciate a feedback on the comments in the files.
General remarks (that should not hinder the merge):
- I am not that deep into grouping, so I cannot say if everything is fine there.
- Documentation should undergo an overall revision anyway, but this is a separate issue -- so, very nice contribution!
- Local build of the API documentation did not work - is it a problem of this PR or with the dev branch? (or at my machine?)
- Do we need the init.py in the examples? The others do not have an init either, so remove it?
- The repository will become very large if we include many examples with a dataset of 8760 time steps -- Is this wanted?
@@ -0,0 +1,8761 @@ | |||
Demand,SolarGen |
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 think it is not a good practice to have such large files for testing purposes. Do you really need that? Could you reduce this to 10 time steps?
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 need to trim it to the minimum time required to be able to see the difference with the non_convex without invest problem
investment_costs += ( | ||
self.invest[i, o] * m.flows[i, o].investment.ep_costs | ||
+ m.flows[i, o].investment.offset | ||
) |
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.
investment_costs += ( | |
self.invest[i, o] * m.flows[i, o].investment.ep_costs | |
+ m.flows[i, o].investment.offset | |
) | |
investment_costs += ( | |
self.invest[i, o] * m.flows[i, o].investment.ep_costs | |
) |
The offset simply adds a fixed value to your objective independent of the investment decision. I think this should be removed.
This was probably left from a failed attempt to reuse the example in the tests (so one would need to be able to import the example) |
Explanation:
This new class represents a new
Flow
which combines bothInvestment
andNonConvex
classes and provides the possibility to perform the capacity optimization of an asset considering min/max loads (i.e., percentages of the capacity which is being optimized), as well as the status of the operation.It must be noted since in the
NonConvexInvestmentFlow
a binary variable (status
of the flow at each time) is multiplied by a continuous variable,invest
, which is the capacity of the asset being optimized, the problem becomes non-linear. For some solvers such as gurobi, this kind of non-linearity is automatically linearized (probably using the big M method), but in other free solvers such as cbc, this causes an error in the optimization. For this reason, those nonlinearities are addressed by introducing a new variable callednew_param
and adding three new constraints.Example:
The following diagrams show a good comparison between the
Investment
and theNonConvexInvestment
flows. These diagrams are duration curves of a diesel genset optimized for a mini-grid with the same input for both optimizations. As seen in the figures, assuming that the diesel genset has a minimum load of 20%, theInvestment
flow would result in an infeasible operation of this device for more than 40% of its annual operation. However, this would never happen using theNonConvexInvestment
flow because it considers the minimum load of the genset during the optimization.Moreover, the optimal capacity using the
NonConvexInvestment
flow is significantly different from the one obtained from theInvestment
flow.