Storage

  • File name: storage.py

  • Last edited: 2020-06-14

  • Created by: Stefan Bruche (TU Berlin)

A storage component can collect a commodity at the inlet at one time step and make it available at the outlet at another time step. Thus, it is a component to provide flexibility.

class aristopy.storage.Storage(ensys, name, inlet, outlet, basic_variable='inlet_variable', has_existence_binary_var=False, time_series_data=None, scalar_params=None, additional_vars=None, user_expressions=None, capacity=None, capacity_min=None, capacity_max=None, capacity_per_module=None, maximal_module_number=None, capex_per_capacity=0, capex_if_exist=0, opex_per_capacity=0, opex_if_exist=0, opex_operation=0, charge_rate=1, discharge_rate=1, self_discharge=0, charge_efficiency=1, discharge_efficiency=1, soc_min=0, soc_max=1, soc_initial=None, use_inter_period_formulation=True, precise_inter_period_modeling=False)[source]

Initialize an instance of the Storage class.

Note

See the documentation of the Component class for a description of all keyword arguments and inherited methods.

Parameters
  • charge_rate (float or int (>=0)) – Ratio between the maximum charging power or flow and the storage capacity. It indicates the reciprocal value of the time for a full storage charging process from empty to full (e.g., ‘charge_rate’=1/6 => 6 hours needed to load an empty storage fully).
    Default: 1

  • discharge_rate (float or int (>=0)) – Ratio between the maximum discharging power or flow and the storage capacity. It indicates the reciprocal value of the time for a full storage discharging process from full to empty (e.g., ‘discharge_rate’=1/6 => 6 hours needed for emptying a fully loaded storage).
    Default: 1

  • self_discharge (float or int (0<=value<=1)) – Share of the storage content that is dissipated and can not be used (e.g., heat losses to the environment for a heat storage). The value is specified in “percent per hour” [%/h].
    Default: 0

  • charge_efficiency (float or int (0<=value<=1)) – Efficiency value for the charging process. It indicates the ratio between stored and entering commodities. E.g., ‘charge_efficiency’=0.9 => for 1 MWh entering the storage in one time step 0.9 MWh are stored, and 0.1 MWh are lost.
    Default: 1

  • discharge_efficiency (float or int (0<=value<=1)) – Efficiency of the discharging process. It indicates the ratio between the usable commodity at the outlet and the reduction in the stored commodity. E.g., ‘discharge_efficiency’=0.9 => if SOC is reduced by 1 MWh in one time step, 0.9 MWh are available at the outlet, and 0.1 MWh are lost.
    Default: 1

  • soc_min (float or int (0<=value<=1)) – Relative value to provide a lower bound for the usable storage capacity. E.g., with a storage capacity of 5 MWh and a value for ‘soc_min’ given with 0.2, the SOC cannot fall below 1 MWh.
    Default: 0

  • soc_max (float or int (0<=value<=1)) – Relative value to provide an upper bound for the usable storage capacity. E.g., with a storage capacity of 5 MWh and a value for ‘soc_max’ given with 0.8, the SOC cannot exceed 4 MWh.
    Default: 1

  • soc_initial (float or int (0<=value<=1), or None) – Provides a value for the relative state of charge in the first time step of the optimization problem (e.g., 0.5 => 50%). The initial SOC value is applied to all periods if the model has multiple periods (calculation with clustered data), and the keyword argument ‘use_inter_period_formulation’ is set to False.
    Default: None

  • use_inter_period_formulation (bool) – States whether a model formulation should be applied that connects the states of charge of a storage component for otherwise independent periods (only used if time series aggregation is applied). Additional variables and constraints are created if the keyword argument is set to True. This formulation enables the (energy) transport between periods (especially relevant for long-term storages) and likewise increases the model complexity.
    Default: True

  • precise_inter_period_modeling (bool) – States whether the inter-period formulation should be implemented in a simplified (False) or precise (True) way. The type of formulation influences how the constraints are modeled that enforce the SOC’s bounds. If the storage has only a low self-discharge value, it is recommended to choose the simplified version (False). This version introduces some additional variables, but requires a significantly smaller number of constraints (Ref: DOI 10.1016/j.apenergy.2018.01.023).
    Default: False

declare_component_constraints(ensys, model)[source]

Method to declare all component constraints.

The following constraint methods are inherited from the Component class and are not documented in this sub-class:

Method is not intended for public access!

Parameters
  • ensys – Instance of the EnergySystem class

  • model – Pyomo ConcreteModel of the EnergySystem instance

con_operation_limit(model)[source]

The state of charge (SOC) of a storage component is limit by its nominal capacity in all time steps. E.g.:
SOC[p, t] <= CAP

Method is not intended for public access!

con_soc_balance(ensys, model)[source]

Constraint that connects the state of charge (SOC) of each time step with the charging and discharging events. The change in the SOC between two points in time has to match the values of charging and discharging and the self-discharge of the storage (explicit Euler formulation). Note: The SOC is not necessarily a value between 0 and 1 here. E.g.,
SOC[p, t+1] <= SOC[p, t]*(1-self_dischar)**dt + Q_IN[p, t]*eta_char - Q_OUT[p, t]/eta_dischar

Method is not intended for public access!

con_charge_rate(ensys, model)[source]

Constraint to limit the value of the charge variable by applying a maximal charge rate. E.g.:
Q_IN[p, t] <= CAP * charge_rate * dt

Method is not intended for public access!

con_discharge_rate(ensys, model)[source]

Constraint to limit the value of the discharge variable by applying a maximal discharge rate. E.g.:
Q_OUT[p, t] <= CAP * discharge_rate * dt

Method is not intended for public access!

con_cyclic_condition(ensys, model)[source]

Constraint to enforce that the SOC in the last time step of a period (after charging and discharging events) equals the SOC at the beginning of the same period. In case the inter-period formulation is activated, this constraint demands that the cycle condition is also fulfilled for the full time scale problem => SOC in global first time step (e.g., SOC[t=1]) equals SOC in global last time step (e.g., SOC[t=8760]).

Method is not intended for public access!

con_soc_initial(ensys, model)[source]

Constraint that sets a value for the relative state of charge in the first time step of the optimization problem. The same initial SOC value is applied to all periods if the model has multiple periods. Otherwise, the initial value is only specified for very beginning of the time set. E.g.:
SOC[p, 0] == CAP * soc_initial or
SOC_INTER[0] == CAP * soc_initial

Method is not intended for public access!

con_soc_intra_period_start(ensys, model)[source]

The state of charge consists of two parts (Intra and Inter), if the intra-period model formulation (‘use_inter_period_formulation’=True) is selected. This constraint sets the intra-period part (SOC) to zero at the beginning of each period. E.g.:
SOC[p, 0] == 0

Method is not intended for public access!

con_soc_inter_period_balance(ensys, model)[source]

Constraint to calculate the inter-period state of charge (SOC_INTER) of the next period from the previous one and the value of the SOC (Intra) in the last time step of the related typical period. The constraint also accounts for self-discharge losses associated with the variable SOC_INTER (=> this can result in steps in the overall SOC profile at the boundary of 2 periods). E.g.:
SOC_INTER[p+1] == SOC_INTER[p]*(1-self_dischar)**( time_steps_per_period*dt) + SOC[typ_p, last_t]

Method is not intended for public access!

con_soc_bounds_without_inter_period_formulation(ensys, model)[source]

Two constraints that specify bounds for the state of charge variable (minimal and maximal values) in case the inter-period formulation is NOT selected, or the data is NOT clustered! E.g.:
SOC[p, t] >= CAP * soc_min and
SOC[p, t] <= CAP * soc_max

Method is not intended for public access!

con_soc_bounds_with_inter_period_formulation_simple(ensys, model)[source]

Four constraints that define the bounds for the state of charge variable (minimal and maximal values) in a simplified way in case the inter- period formulation is requested and the data is clustered. The error is relatively small in comparison to the precise method if the specified value for the ‘self_discharge’ is not too high. However, this version requires a reasonable smaller number of constraints but also some additional variables.
See Eq. B1 and B2 in the Appendix of Ref: DOI 10.1016/j.apenergy.2018.01.023.

Method is not intended for public access!

con_soc_bounds_with_inter_period_formulation_precise(ensys, model)[source]

Two constraints define the bounds for the state of charge variable (minimal and maximal values) in a precise way if the inter-period formulation is requested, and the data is clustered. This version requires two constraints for each time step of the full- scale problem and can be computationally expensive. Users might want to consider applying the simplified constraint formulation (keyword argument ‘precise_inter_period_modeling’=False).
See Eq. 20 in Ref: DOI 10.1016/j.apenergy.2018.01.023.

Method is not intended for public access!

serialize()[source]

This method collects all relevant input data and optimization results from the Component instance, and returns them in an ordered dictionary.

Returns

OrderedDict