Oemof in combination with time series aggregation module (tsam)

Hello all,
I am currently building an energy system model in oemof and I want to use time series aggregation to reduce its complexity. For the time series aggregation I use the tool TSAM (GitHub - FZJ-IEK3-VSA/tsam: Time series aggregation module (tsam). Determines typical operation periods or dereases the temporal resolution. Accelerates model or experiment runs.).

The question is now how to index my energy system when I use
solph.EnergySystem()

Basic example to clarify:
-I have a time series with hourly values of the year 2050, means 8760 values.

                           electricity     wind   pv
timeindex                                           
2050-01-01 00:00:00+00:00     0.000099  0.86580  0.0
2050-01-01 01:00:00+00:00     0.000095  0.87275  0.0
2050-01-01 02:00:00+00:00     0.000091  0.85540  0.0
2050-01-01 03:00:00+00:00     0.000088  0.84455  0.0
2050-01-01 04:00:00+00:00     0.000086  0.83700  0.0
                               ...      ...  ...
2050-12-31 19:00:00+00:00     0.000103  0.22250  0.0
2050-12-31 20:00:00+00:00     0.000094  0.21310  0.0
2050-12-31 21:00:00+00:00     0.000091  0.21815  0.0
2050-12-31 22:00:00+00:00     0.000092  0.25315  0.0
2050-12-31 23:00:00+00:00     0.000088  0.32810  0.0

[8760 rows x 3 columns]

Here the indexing in oemof is clear.
my_energysystem = solph.EnergySystem(timeindex = pd.date_range('1/1/2050', periods=8761, freq='H'))

-But if I now aggregate this time series to 5 typical days I get a data set that looks like this:

                           electricity     wind   pv
TimeStep                                 
0 0            0.000086  0.000000  0.623217
  1            0.000084  0.000000  0.647247
  2            0.000084  0.000000  0.671063
  3            0.000087  0.000000  0.689871
  4            0.000092  0.013594  0.700474
                ...       ...       ...
4 19           0.000131  0.000000  0.089345
  20           0.000122  0.000000  0.107194
  21           0.000112  0.000000  0.122432
  22           0.000101  0.000000  0.128346
  23           0.000092  0.000000  0.120568

[120 rows x 3 columns]

The index of this data set is a MultiIndex, the first number represents the typical day and the second number represents the timestep (each period has 24 timesteps, so in total there are 5*25=120 rows). Each typical day is additionally assigned a weight, how often it occurs within a year.

Can you tell me how to define my energy system in the case of typical periods? I would be grateful for the reference to a code in which oemof has been used in connection with typical periods.

Please tell me if I need to clarify my question.
Many thanks in advance!

Best,
Emilia

Hi Emilia,

actually, the choice of representation depends on you energy system:

  • If you have no energy storage, you could just append those five days and treat them as if they were fife consecutive days. (You can create an arbitrary time index for that, as long as it has the same resolution.)
  • If you have energy storage only for small periods of time, you might still get away with that. It might be cleaner though, to decouple the days. If there is no investment optimization, I would just split it to five runs. If there is, multi-period optimization might do the job but I did not test that yet. (There are alternatives, but I did not try any.)
  • If you have seasonal storage, type days become tricky. If your model is purely linear (i.e. no minimal or maximal loads or any other mixed integer formulation), attributing realistic calendar days to the type days can help. Additionally, you would need some “average” data for the time in between. This way, you could fill you year with time steps of variable length. If you rely on mixed integer formulation and find a way to work with seasonal storage and type days, please let me know. I’d like to learn.

Cheers,
Patrik

Hi Patrick,

thank you very much for your fast respond!
for the basic case this helps me a lot. In this case do I need to weight the typical days according to their number of occurences within one year?

Regarding your last point about seasonal storage, there seem to be several approaches to this, the best known is probably the one by Kotzur et al. in their paper: “Time series aggregation for energy system design: Modeling seasonal storage” (https://www.sciencedirect.com/science/article/abs/pii/S0306261918300242).
Do I understand it correctly that there is no known way in oemof to implement this approach with the two different time layers?

image

Best,
Emilia

Hi @Emilia,

thanks for continuing the discussion. You are right. It makes a lot of sense to weight the typical days.

For the combination of time series aggregation and seasonal storage, I just do not know if anybody did that yet. We might have laid out the fundament for the suggested formulation by introducing periods as a second time index, but this was done periodic investments in mind, so some important functionality is probably missing. (I do not have a deep understanding of the periods, yet, but I am willing to look into the options.)

Cheers,
Patrik

Hi @Emilia and @pschoen,

that’s quite an interesting subject you touch upon. Since I introduced the period time index in oemof.solph, I can tell that the functionality you refer to (time interlinkage of storage using another time index level - they refer to it as inter-period storage states) is not yet implemented in oemof.solph. The use case of what is referred to as periods in oemof.solph is investments modelling compared to handling aggregated (dispatch) time series here.

It would be nice to have this in oemof.solph, though - Feel free to open a feature request or even implement it. There is a formulation within the FINE framework developed and maintained by FZJ if I’m not mistaken which you might want to refer to: https://github.com/FZJ-IEK3-VSA/FINE/blob/master/FINE/storage.py
It’s been a while since I digged into the code (superficially), but it should contain the functionality you mention and what is more, is also based on pyomo to my knowledge and judging from the import statement at the very top.

Best regards,
Johannes

Hi @dlr_jk and @pschoen,
Thank you both for your input! I would try to implement it myself in oemof, as I need this feature relatively soon. Is there anyone I can contact if I have any questions? I have already tried to get an overview of all classes, but that is of course difficult at the beginning with such an extensive package.
Best,
Emilia

I think it’s best to open an issue (and later a PR) at Issues · oemof/oemof-solph (github.com). This is where most devs look at.

PS: I supervise a PhD candidate who might also be interested in this. He needs binary constraints and is thus yearning for things that speed up the optimisation. I would hint him to the issue, once it exists.