Representative days with seasonal storages

In order to reduce computational times, representative periods are often used in optimization models. However, this often limits the ability to properly account for seasonal storages.

In SpineOpt, we provide functionality to use representative days with seasonal storages in combination with the package SpinePeriods.jl.

General idea

The general idea is to mimick the seasonal effects throughout a non-representative period, e.g. a year of optimization, by introducing a specific sequence of the representative periods. Taking the example of one year to be optimized with representative days and seasonal storages, SpinePeriods.jl provides a mapping of each day of the year to its corresponding representative day. This information is stored in the mapping parameter representative_periods_mapping and is defined on the temporal_block for the whole year. The representative_periods_mapping parameter is a timeseries, pointing the beginning of each day to its corresponding representative day temporal_block, which can also be automatically be generated through SpinePeriods.jl.

In SpineOpt, this is interpreted in the following way:

  • All operational variables, with the exception of the node_state variable, are created for each representative period. For each non-representative period, the variables are mapped to their corresponding variable of the representative periods according to the representative_periods_mapping parameter.
  • Only the node_state variables and all investment variables are created for both, representative and non-representative period (of course, depending on the existance of relationships to temporal_blocks).

Usage of representative days and seasonal storages for investment problems

To make use of representative days with seasonal storages concept, multiple temporal_block objects need to be created and connected to the system components, holding information about the resolutions in different parts of the model that come into play. As described in the section Temporal Framework, every temporal block needs to be connected to a model object.

  • temporal_block for investments: In order to define the resolution of the investment decisions, a temporal_block relecting the frequency of investment decisions should be introduced. For yearly investment, the resolution of this temporal block would be equal to 1Y. In order to link nodes, units or connections to this investment resolution, the node__investment_temporal_block, unit__investment_temporal_block, or connection__investment_temporal_block relationships need to be defined, respectively. For more details on investments, see also section Investment Optimization
  • temporal_block for representative days: For each representative day, one temporal_block needs to be created, indicating the block_start and block_end of the representative day. The use of disconnected periods is also described in the section Disconnected time periods. The resolution of the representative days corresponds to the resolution of the operational variables, e.g. 1h. In order to associate operational variables with the representative periods, node__temporal_block and units_on__temporal_block relationships need to be created. For convenience, it is also possible to create a group of all representative temporal_blocks and link this group to these relationships. Note that, when using SpinePeriods.jl, the representative temporal blocks are auto-generated.
  • temporal_block for non-representative days: To introduce node_state variables for the entire operational period, a temporal block overarching the entire horizon is created. Note that currently, this temporal block needs to have the same resolution as the representative days, e.g. 1h. In order to associate operational variables with the representative periods, node__temporal_block and units_on__temporal_block relationships need to be created. Note that, as described above, the non-representative variables, will be mapped to their corresponding representative days. To manually introduce the mapping between non-representative and representative periods, instead of using the recommended SpinePeriods.jl, the user must define the mapping parameter representative_periods_mapping by hand, consisting of DateTime indices (indicating the start of each non-representative period, e.g. for a daily mapping 2021-01-01T00:00:00, 2021-01-02T00:00:00 etc.) and the name of the corresponding representative temporal_block as a value.