-
Notifications
You must be signed in to change notification settings - Fork 135
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
Features/schedule for flow #666
base: dev
Are you sure you want to change the base?
Changes from 16 commits
c34d5e7
c49a010
0887645
b760396
ea2e2ff
78fceff
8bd7dda
650f9ec
e264e5a
a9ca25a
46cc201
c7882a9
d5e5f6c
2d89775
151576d
97d94b0
31397a1
bd43f3e
a7709af
cbabaa7
f71ae4a
54fa08e
4a7106f
c65349c
fab3209
810ea70
ecf0c67
0b07a2c
36d7ad0
2a66fc2
abab4ea
5f63483
3048635
5b5d328
15d32d1
0cd492b
564c7e7
9a2b0fd
a31aed0
c51772b
2c3f8f1
0436ab1
134ec9a
4ba1c2c
c948e6d
346e687
b6cefa2
5ec2d0d
40e0a9f
f37c523
309ba2e
5a7a4de
589d230
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
v0.3.3 (??, ??) | ||
+++++++++++++++++++++++++++ | ||
|
||
|
||
API changes | ||
########### | ||
|
||
* something | ||
|
||
New features | ||
############ | ||
|
||
* It is now possible to determine a schedule for a flow. Flow will be pushed | ||
to the schedule, if possible. | ||
|
||
New components | ||
############## | ||
|
||
* something | ||
|
||
Documentation | ||
############# | ||
|
||
* something | ||
|
||
Known issues | ||
############ | ||
|
||
* something | ||
|
||
Bug fixes | ||
######### | ||
|
||
* something | ||
|
||
Testing | ||
####### | ||
|
||
* something | ||
|
||
Other changes | ||
############# | ||
|
||
* something | ||
|
||
Contributors | ||
############ | ||
|
||
* Caterina Köhl |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,6 +117,23 @@ class Flow(on.Edge): | |
:class:`Flow <oemof.solph.blocks.Flow>`. | ||
Note: at the moment this does not work if the investment attribute is | ||
set . | ||
schedule : numeric (sequence or scalar) | ||
Schedule for the flow. Flow has to follow the schedule, otherwise a | ||
penalty term will be activated. If array-like, values can be None | ||
for flexible, non-fixed flow during the certain timestep. Used in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this work actually, i.e. setting someting like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tested it and it worked. But I'm confused now, because you're actually right. Usually pyomo is not amused if None is provided. I will add a "return Constraint.Skip" for completeness There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I think it is possible, because of BuildAction no return value has to be provided and the constraints will be added by add() function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I tried adding the return value Constraints.Skip, but as soon as it will be returned once, pyomo quits the constraint completely and continues with the next constraint. So in your case (schedule = [1, 2, None, 3]), the flow will only follow the schedule until the first None: [1, 2, None]. Everything following the first None will not be handled. |
||
combination with :attr:`penalty_pos` and :attr:`penalty_neg`. | ||
penalty_pos : numeric (sequence or scalar) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should there be a high default value of something like 10e9 force the schedule kind of by default? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was also thinking about adding a default value. It's actually more user friendly. I think it depends on what kind of users are working with oemof. Do you think it will be necessary? I can easily add one :-) |
||
A penalty parameter of the penalty term which describes the costs | ||
associated with one unit of deficit of the flow compared to the | ||
schedule. If this is set the costs will be added to the objective | ||
expression of the optimization problem. Used in combination with the | ||
:attr:`schedule` and :attr:`penalty_neg` | ||
penalty_neg: numeric (sequence or scalar) | ||
A penalty parameter of the penalty term which describes the costs | ||
associated with one unit of the exceeded flow when flow exceeds the | ||
schedule. If this is set the costs will be added to the objective | ||
expression of the optimization problem. Used in combination with | ||
the :attr:`schedule` and :attr:`penalty_pos` | ||
|
||
Notes | ||
----- | ||
|
@@ -157,11 +174,13 @@ def __init__(self, **kwargs): | |
|
||
scalars = ['nominal_value', 'summed_max', 'summed_min', | ||
'investment', 'nonconvex', 'integer', 'fixed'] | ||
sequences = ['actual_value', 'variable_costs', 'min', 'max'] | ||
sequences = ['actual_value', 'variable_costs', 'min', 'max', | ||
'schedule', 'penalty_neg', 'penalty_pos'] | ||
dictionaries = ['positive_gradient', 'negative_gradient'] | ||
defaults = {'fixed': False, 'min': 0, 'max': 1, 'variable_costs': 0, | ||
'positive_gradient': {'ub': None, 'costs': 0}, | ||
'negative_gradient': {'ub': None, 'costs': 0}, | ||
'penalty_neg': 0, 'penalty_pos': 0, 'schedule': None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking if this could not rather be implemented like the gradient cost stuff as a dictionary to reduced number of attributes. It seems better to me, but again-> there are always multiple ways. Maybe ask @gnn for this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for taking so long to review this one... :-/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm I do not know about this one. I personally think it can be helpful, if the user can determine during what timesteps he will punish the system harder or being more "relaxed" if flow can not follow the schedule. No worries, we are all busy and even holidays were in between :-) |
||
} | ||
keys = [k for k in kwargs if k != 'label'] | ||
|
||
|
@@ -188,6 +207,13 @@ def __init__(self, **kwargs): | |
if self.investment and self.nonconvex: | ||
raise ValueError("Investment flows cannot be combined with " + | ||
"nonconvex flows!") | ||
if ( | ||
len(self.schedule) != 0 and | ||
((len(self.penalty_pos) == 0 and not self.penalty_pos[0]) or | ||
(len(self.penalty_neg) == 0 and not self.penalty_neg[0]))): | ||
raise ValueError("The penalty and schedule attribute need " | ||
"to be used in combination. \n Please set " | ||
"the schedule attribute of the flow.") | ||
|
||
|
||
class Bus(on.Bus): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
\* Source Pyomo model name=Model *\ | ||
|
||
min | ||
objective: | ||
+999 Flow_slack_neg(boiler_penalty_bus_th_penalty_0) | ||
+999 Flow_slack_neg(boiler_penalty_bus_th_penalty_1) | ||
+999 Flow_slack_neg(boiler_penalty_bus_th_penalty_2) | ||
+800 Flow_slack_pos(boiler_penalty_bus_th_penalty_1) | ||
+900 Flow_slack_pos(boiler_penalty_bus_th_penalty_2) | ||
|
||
s.t. | ||
|
||
c_e_Bus_balance(bus_gas_0)_: | ||
+1 flow(bus_gas_boiler_penalty_0) | ||
= 0 | ||
|
||
c_e_Bus_balance(bus_gas_1)_: | ||
+1 flow(bus_gas_boiler_penalty_1) | ||
= 0 | ||
|
||
c_e_Bus_balance(bus_gas_2)_: | ||
+1 flow(bus_gas_boiler_penalty_2) | ||
= 0 | ||
|
||
c_e_Bus_balance(bus_th_penalty_0)_: | ||
+1 flow(boiler_penalty_bus_th_penalty_0) | ||
= 0 | ||
|
||
c_e_Bus_balance(bus_th_penalty_1)_: | ||
+1 flow(boiler_penalty_bus_th_penalty_1) | ||
= 0 | ||
|
||
c_e_Bus_balance(bus_th_penalty_2)_: | ||
+1 flow(boiler_penalty_bus_th_penalty_2) | ||
= 0 | ||
|
||
c_e_Transformer_relation(boiler_penalty_bus_gas_bus_th_penalty_0)_: | ||
-1 flow(boiler_penalty_bus_th_penalty_0) | ||
+1 flow(bus_gas_boiler_penalty_0) | ||
= 0 | ||
|
||
c_e_Transformer_relation(boiler_penalty_bus_gas_bus_th_penalty_1)_: | ||
-1 flow(boiler_penalty_bus_th_penalty_1) | ||
+1 flow(bus_gas_boiler_penalty_1) | ||
= 0 | ||
|
||
c_e_Transformer_relation(boiler_penalty_bus_gas_bus_th_penalty_2)_: | ||
-1 flow(boiler_penalty_bus_th_penalty_2) | ||
+1 flow(bus_gas_boiler_penalty_2) | ||
= 0 | ||
|
||
c_e_Flow_schedule_constr(boiler_penalty_bus_th_penalty_1)_: | ||
-1 Flow_slack_neg(boiler_penalty_bus_th_penalty_1) | ||
+1 Flow_slack_pos(boiler_penalty_bus_th_penalty_1) | ||
+1 flow(boiler_penalty_bus_th_penalty_1) | ||
= 300 | ||
|
||
c_e_Flow_schedule_constr(boiler_penalty_bus_th_penalty_2)_: | ||
-1 Flow_slack_neg(boiler_penalty_bus_th_penalty_2) | ||
+1 Flow_slack_pos(boiler_penalty_bus_th_penalty_2) | ||
+1 flow(boiler_penalty_bus_th_penalty_2) | ||
= 50 | ||
|
||
c_e_ONE_VAR_CONSTANT: | ||
ONE_VAR_CONSTANT = 1.0 | ||
|
||
bounds | ||
0 <= flow(boiler_penalty_bus_th_penalty_0) <= 200 | ||
0 <= flow(boiler_penalty_bus_th_penalty_1) <= 200 | ||
0 <= flow(boiler_penalty_bus_th_penalty_2) <= 200 | ||
0 <= flow(bus_gas_boiler_penalty_0) <= +inf | ||
0 <= flow(bus_gas_boiler_penalty_1) <= +inf | ||
0 <= flow(bus_gas_boiler_penalty_2) <= +inf | ||
0 <= Flow_slack_pos(boiler_penalty_bus_th_penalty_1) <= +inf | ||
0 <= Flow_slack_pos(boiler_penalty_bus_th_penalty_2) <= +inf | ||
0 <= Flow_slack_neg(boiler_penalty_bus_th_penalty_0) <= +inf | ||
0 <= Flow_slack_neg(boiler_penalty_bus_th_penalty_1) <= +inf | ||
0 <= Flow_slack_neg(boiler_penalty_bus_th_penalty_2) <= +inf | ||
end |
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 these could be named to schedule_slack_pos, but I am not sure...It's also fine for me like this. Naming is always so controversial ;-)
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 like your idea. It is always better to be a little bit more specific and if we put "schedule" into the variable names, everybody knows where they belong to.