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

Implementation of explicit storage equations in MESSAGE #162

Closed
behnam-zakeri opened this issue Feb 4, 2019 · 5 comments
Closed

Implementation of explicit storage equations in MESSAGE #162

behnam-zakeri opened this issue Feb 4, 2019 · 5 comments
Labels
enh New features & functionality timeslice

Comments

@behnam-zakeri
Copy link
Contributor

Motivation:
There are different ways to represent storage (such as electricity storage, water storage, heat storage, etc.) using the current mathematical model in message_ix. However, it may be more efficient to add explicit equations represnting storage technologies and their functionality. This issue is opened to discuss the best way of doing this so that the added equations will serve as many as possible storage technologies and applications.

Requirements:
In this context, the desired equations should meet the following requirements:

  • providing the possibility to invest in some storage technologies for shifting a specified commoditiy (like electricity) between subannual time steps
  • showing the state of storage at any sub-annual time interval
  • ensuring the state of storage is the same at the beginning and end of the year (any desire for inter-year storage?)
  • represnting the storage losses ideally relative to the duration of storage (number of sub-annual time steps)
  • being consistent with other equations, like COMMODITY_BALANCE

Please add your views and comments in this thread, and we try to synthesize the best possible way forewards.

@behnam-zakeri behnam-zakeri changed the title Implementation of explicit storage technologies in MESSAGE Implementation of explicit storage equations in MESSAGE Feb 4, 2019
@behnam-zakeri
Copy link
Contributor Author

Adriano's suggestion:
This method is based on the changes in commodity balance equation and adding a new block of equations for storage:

  1. Adding the following lines to COMMODITY_BALANCE to represnt quantity taken out from ( >0 ) or put into ( <0 ) inter-period stock (storage):
    _+ STOCK_CHG(node,commodity,level,year,time)$( map_stocks(node,commodity,level,year) )

    • STORAGE_CHG(node,commodity,level,year,time)$( map_storage(node,commodity,level,year,time) AND bound_storage_up(node,commodity,level,year,time) )_
      image
  2. Adding storage equations (including CAP variable and a possible mapping in the BOUND equations):
    STORAGE_BALANCE(node,commodity,level,year,time)$( map_storage(node,commodity,level,year,time) AND bound_storage_up(node,commodity,level,year,time) )..
    STORAGE(node,commodity,level,year,time)

  • fixed level of storage (i.e. in first period)
    - commodity_storage(node,commodity,level,year,time) =E=
    ( storage_to_activity(time)*STORAGE_CHG(node,commodity,level,year,time) )
  • the next line is just saying STORAGE(t-1)
    + SUM((time2,year2)$seq_year_time(year2,year,time2,time), STORAGE(node,commodity,level,year2,time2) *
    (1 - storage_loss(node,commodity,level,year2,time2)) ) ;

STORAGE_BOUND_UP(node,commodity,level,year,time)$( map_storage(node,commodity,level,year,time) AND bound_storage_up(node,commodity,level,year,time) )..
STORAGE(node,commodity,level,year,time) =L= map_storage_tec(node,tec,commodity,level,year,time) * CAP(node,tec,vintage,year) ;

STORAGE_BOUND_LO(node,commodity,level,year,time)$( map_storage(node,commodity,level,year,time) AND bound_storage_up(node,commodity,level,year,time) )..
STORAGE(node,commodity,level,year,time) =G= map_storage_tec(node,tec,commodity,level,year,time) * CAP(node,tec,vintage,year) *
storage_lo_factor(node,commodity,level,year,time) ;

image

pictures are attached for a clearer notation in GAMS.

@behnam-zakeri
Copy link
Contributor Author

Technology-based storage implementation
This alternative is based on introducing two technologies as charger and discharger for storing a commodity and discharging that from storage, respectively. This resembles the pump and turbine sections in a pumped hydropower storage plant. The two technologies can be incorporated in one but working in two different "mode"s. The storage media itself will be another technology (like a dam).
The advantage here is that the techno-environmental-economic parameters of the charging and discharging technologies can be conveniently specified in the model, using the current parameters. For example, technologies can have their own efficiency, investment and O&M costs, emissions (if any), etc., independent from the storage media.

To implement this storage model:

  1. Charging and discharging technologies should be specified in the model input parameters. This can be done by, first, specifying storage levels, such as introducing a set called "level_storage" similar to "level_renewable", for example. Then, those technologies with input and output to this storage level can be mapped as “charge_tec” and “discharge_tec”, and both technologies together as storage technologies, "storage_tec".

  2. The order of subannual timesteps will be defined by the user in a set or parameter called “seq_time”. This will be a dataframe showing the order as a number for each subannual time step, e.g., 1 for “Jan”, etc.

  3. In the “period_parameter_assignment” file of the model, the sequence of time and year together will be defined as:

image
Each subsequent time step can be either in the same year or in the next ones.

  1. Activity (ACT) of storage technologies will define the change in the storage content. This will replace the part called "STORAGE_CHG" in the first implementation alternative above. Hence, the “STORAGE” equation, which drives the content of storage, will look like:
    image

  2. The upper bound and lower bound on the content of storage can be defined as follows. If storage media will be introduced as a technology itself, for example a dam, then the installed capacity (CAP) of that technology multiplied by “capacity_factor” will be the upper bound of storage content. the lower bound should be explicitly defined by the user for each subannual timestep as “bound-storage_lo”. These two bounds can be as the following:
    image

@JulianHunt4
Copy link

Simple Approach to Add Seasonal Storage to MESSAGE
Behnam has proposed a possibility for adding seasonal storage technologies to MESSAGE. The approach is simple to understand and implement. We have implemented and it seams to work well.

It consists of creating a new technology, for example, 'stor_SPS' in which the 'electricity' input and output months are explicitly entered in the technology, as presented below using the Austria Tutorial example:

The months in which the SPS plant stores energy are explicitly added to the model.

base_input = {'node_loc': country,'year_vtg': vintage_years,'year_act': act_years,'mode': 'standard','node_origin': country,'commodity': 'electricity','time': '1','time_origin': '1',}
water_in_SPS = make_df(base_input, technology = 'stor_SPS',commodity='electricity', level = 'secondary',value = 1.2, unit = '%')
base_input = { // 'time': '4','time_origin': '4' //}
base_input = { // 'time': '5','time_origin': '5' //}
base_input = { // 'time': '6','time_origin': '6' //}
base_input = { // 'time': '7','time_origin': '7' //}
base_input = { // 'time': '8','time_origin': '8' //}
base_input = { // 'time': '9','time_origin': '9' //}

The months in which the SPS plant generates electricity are explicitly added to the model.

base_output = {'node_loc': country,'year_vtg': vintage_years,'year_act': act_years,'mode': 'standard','node_dest': country,'time': '1','time_dest': '1','unit': '%',}
water_out_SPS = make_df(base_output, technology='stor_SPS', commodity='electricity',level='secondary', value=1.0, unit = '%')
base_output = { // 'time': '1','time_origin': '1' //}
base_output = { // 'time': '2','time_origin': '2' //}
base_output = { // 'time': '3','time_origin': '3' //}
base_output = { // 'time': '10','time_origin': '10' //}
base_output = { // 'time': '11','time_origin': '11' //}
base_output = { // 'time': '12','time_origin': '12' //}

The capacity factor for the input and output should change with months, according to the intended operation of the plant.

base_capacity_factor = {'node_loc': country,'year_vtg': vintage_years,'year_act': act_years,''time'': '1','unit': '%',}
df = make_df(base_capacity_factor, technology='stor_SPS', value=0.8)
base_capacity_factor = // 'time'': '2' // df = // value=0.4)
base_capacity_factor = // 'time'': '3' // df = // value=0.1)
base_capacity_factor = // 'time'': '4' // df = // value=0.1)
base_capacity_factor = // 'time'': '5' // df = // value=0.4)
base_capacity_factor = // 'time'': '6' // df = // value=0.8)
base_capacity_factor = // 'time'': '7' // df = // value=0.8)
base_capacity_factor = // 'time'': '8' // df = // value=0.4)
base_capacity_factor = // 'time'': '9' // df = // value=0.1)
base_capacity_factor = // 'time'': '10' // df = // value=0.1)
base_capacity_factor = // 'time'': '11' // df = // value=0.4)
base_capacity_factor = // 'time'': '12' // df = // value=0.8)

This however, only represents one possible operational scenario in which the technology could be applied. In other to add all other possible operational scenarios, different technology 'modes' should be created. For example, 12 models of the SPS technology could be created to fit the described operation above with different starting months. Alternatively, more models could be created to describe all possible operational variations of the SPS plant.

The advantage of this approach is that it is simple to understand and to implement to MESSAGE. For example, it does not require to change the GAMS equations.

The disadvantage of this approach is that there are infinite scenarios in which the SPS plant could operate and the operation will be restricted to the operational scenarios set in the different 'modes'​.

I will create an example for the Austrian case study and report the finding to share with the group.

@behnam-zakeri
Copy link
Contributor Author

Thank you Julian for the points. The input and output parameters should link the time steps by having a common "time" index. I mean for example:

base_input = { // 'time': '1','time_origin': '1' //}
base_output = { // 'time': '1','time_dest': '12' //}

OR

base_input = { // 'time': '12','time_origin': '1' //}
base_output = { // 'time': '12','time_dest': '12' //}

In the first alternative the technology is active in "time" 1, while in the second it is active in "time" 12. But both alternative does the same task; shifting a commodity from time step 1 to 12.

@behnam-zakeri
Copy link
Contributor Author

behnam-zakeri commented Apr 27, 2019

Thank you all for your input and comments! This issue is closed in favor of PR 190:
#190

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enh New features & functionality timeslice
Projects
None yet
Development

No branches or pull requests

2 participants