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

Multi-period investment optmization: no investment in first period #1029

Open
SabineHaas opened this issue Nov 30, 2023 · 6 comments
Open

Multi-period investment optmization: no investment in first period #1029

SabineHaas opened this issue Nov 30, 2023 · 6 comments

Comments

@SabineHaas
Copy link
Member

Describe the bug
Multi-period investment optimization does not solve as expected. There's no investment into wind and storage in the first period, while the expensive shortage is used to cover the demand. In the second period investment is done as expected into wind and storage, no shortage is used.

Checkout my small example: multi_period.txt

Energy system consists of: el-bus, wind source, el-demand, el-storage, excess, shortage

Also interesting: in the example I run the optimization twice:

  1. wind profile (fix) = [1, 0, 0]
    --> the result is as described above:
    • only in the second period there's investment into wind and storage
    • in the first period the expensive shortage is being used
  2. wind profile (fix) = [0, 1, 0]
    --> result as I would expect it: in first and second period investment into wind and storage and no usage of shortage

To Reproduce
Rund the example code, multi_period.txt

Expected behavior
Investment into wind and storage also in the first period and avoidance of expensive shortage (as in case 2, wind profile = [0, 1, 0]).

Screenshots
Results:

1. wind time series [1, 0, 0]:
wind
variable_name  invest  old  old_end  old_exo  total
period                                             
2020              0.0  0.0      0.0      0.0    0.0
2030            250.0  0.0      0.0      0.0  250.0

 storage
variable_name  invest  old  old_end  old_exo   total
period                                              
2020              0.0  0.0      0.0      0.0     0.0
2030           1500.0  0.0      0.0      0.0  1500.0

 shortage total usage: 
200.0
2. wind time series [0, 1, 0]:
wind
variable_name  invest    old  old_end  old_exo  total
period                                               
2020            225.0    0.0      0.0      0.0  225.0
2030            225.0  225.0    225.0      0.0  225.0

 storage
variable_name  invest    old  old_end  old_exo  total
period                                               
2020            750.0    0.0      0.0      0.0  750.0
2030            750.0  750.0    750.0      0.0  750.0

 shortage total usage: 
0.0

Desktop (please complete the following information):

  • Linux Mint 20.3

  • Python version 3.9

  • oemof.solph version 0.5.2.dev0


@jokochems do you know this behaviour?

This might be interesting for you, @nailend

@jokochems
Copy link
Member

Ouch, that's quite bad, I have to admit. Thanks for pointing this out, @SabineHaas!

I haven't come across this issue, yet, as I have been working with brownfield scenarios, mostly.

I am pretty sure that it relates to the multi-period storage implementation and the definition of the 0th storage state, to be more precise, this code section.

My idea here was to force storage levels to equal 0 until an investment happens. But what the rule effectively does is to prevent storage investments for the 0th (i.e. the very first TIMESTEP).

I commented out the lines mentioned above and the optimization yielded results as you'd have expected them, i.e. no shortage is activated and investment results for both cases are identical.

I haven't given it enough thought yet, but my gut feeling is that the respective rule might be safely removed.

@nailend: Would you second that opinion of mine?

@nailend
Copy link
Contributor

nailend commented Dec 11, 2023

I tried to wrap my head around, but I didn't really understand why this constraint doesn't work. But this is a direct consequence of #1030 isn't it? In multi-period, the distinction between TIMESTEPS and TIMEPOINTS don't exist?

@jokochems
Copy link
Member

I tried to wrap my head around, but I didn't really understand why this constraint doesn't work. But this is a direct consequence of #1030 isn't it? In multi-period, the distinction between TIMESTEPS and TIMEPOINTS don't exist?

Yes, you are right. The two issues are interrelated and there only is the TIMESTEPS set for multi-period models.

  • What I wanted to do - as I describe above - is to ensure new-built storages are initially empty. Now there is the follow-up issue with defining the initial storage level.
  • In the previous version of solph (i.e. before the TIMESTEPS / TIMEPOINTS split), there was an initial storage level defined before any flow happening (so at time -1 if you want to think about it that way). After that, the storage content variables and the flows had the same time indices (from the TIMESTEPS set), wereby the storage content variables were a result of the (in- and out)flows happening into the storage.
  • In the current version of solph, it was decided to make this behaviour explicit by introducing the TIMEPOINTS set with one entry more to properly index storage levels.
  • I wanted to recreate the behaviour of the old solph version (because I found it easier to implement and started with that while the TIMESTEPS / TIMEPOINTS split happened in the meantime). I think the error I made here is that I fixed the 0th instead of the -1st time step with the constraint I referenced.

As I see it, there would be three options:

  1. Simply remove the constraint. This would allow to freely choose a storage level. You'd have to think about whether this might create the model artefact of filling a storage for free, though ...
  2. Adjust the constraint to recreate the behabiour of the previous solph version.
  3. Align with the current version of solph.

I think option 3 is clearly preferrable. In that course, also the investment storage implementation in general should be revised, see #1030.

@p-snft
Copy link
Member

p-snft commented Dec 12, 2023

Simply remove the constraint. This would allow to freely choose a storage level. You'd have to think about whether this might create the model artefact of filling a storage for free, though ...

In fact, the assumption that a newly installed storage is always empty is not valid in all cases. Think of rechargeable batteries: If receive them at 0 % capacity, they are probably broken.

@jokochems
Copy link
Member

Thanks, @p-snft. You are totally right about this. I also thought about pumped storage which will probably come with some filling level initially.

@nailend and @SabineHaas: Look what I found: #965
The constraint was not always there. I added it as sort of a hotfix after I have been informed by a user facing trouble with storages that were initially filled "for free".

@nailend I also had some trouble with proper storage roundtrip conditions (there actually are none yet), but that was before your sophisticated lifetime tracking thing. It might be worth a shot tackling this as well - maybe in a dedicated issue/PR.

@nailend
Copy link
Contributor

nailend commented Dec 15, 2023

Thanks, @p-snft. You are totally right about this. I also thought about pumped storage which will probably come with some filling level initially.

Not sure, what's the better solution to be honest, but I prefer to set the initial content per component.

Look what I found: #965

well I confirmed, haha

@nailend I also had some trouble with proper storage roundtrip conditions (there actually are none yet), but that was before your sophisticated lifetime tracking thing. It might be worth a shot tackling this as well - maybe in a dedicated issue/PR.

you mean roundtrips within a period?

At the dev-meeting, we shared the common interest to somehow replace single-period with multi-period. For this to happen, there are a few things to be done before. I will open an issue, where we can collect the necessary changes/improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants