EnergySystem

  • File name: energySystem.py

  • Last edited: 2020-06-14

  • Created by: Stefan Bruche (TU Berlin)

The EnergySystem class is aristopy’s main model container. An instance of the EnergySystem class holds the modeled components, the overall pyomo model and the results of the optimization. The EnergySystem class provides features to built and solve the optimization problem, manipulate the associated component models, and process the results of the optimization. The implemented class methods are:

class aristopy.energySystem.EnergySystem(number_of_time_steps=8760, hours_per_time_step=1, interest_rate=0.05, economic_lifetime=20, logging=None)[source]

Initialize an instance of the EnergySystem class.

Parameters
  • number_of_time_steps (int (>0)) – Number of considered time steps for modeling the dispatch problem. With “hours_per_time_step” the share of the modeled year can be calculated. In this way, the cost of each time step is scaled and included in the objective function.
    Default: 8760

  • hours_per_time_step (int (>0)) – Number of hours per modeled time step.
    Default: 1

  • interest_rate (float, int (>=0)) – Value to calculate the present value factor of a cost rate that occurs in the future.
    Default: 0.05 (corresponds to 5%)

  • economic_lifetime (int (>0)) – Years to consider for calculating the net present value of an investment with annual incoming and outgoing cash flows.
    Default: 20

  • logging (None or instance of aristopy's "Logger" class) – Specify the behavior of the logging by setting an own Logger class instance. User can decide where to log (file/console) and what to log (see description of aristopy “Logger”).
    Default: None (display minimal logging in the console)

add_variable(var)[source]

Function to manually add pyomo variables to the main pyomo model (ConcreteModel: model) of the energy system instance via instances of aristopy’s Var class. The attributes of the variables are stored in DataFrame “added_variables” and later initialized during the call of function ‘optimize’, or ‘declare_model’.

Parameters

var – Instances of aristopy’s Var class (single or in list)

add_constraint(rule, name=None, has_time_set=True, alternative_set=None)[source]

Function to manually add constraints to the main pyomo model after the instance has been created. The attributes are stored in the DataFrame ‘added_constraints’ and later initialized during the call of function ‘optimize’, or ‘declare_model’.

Parameters
  • rule (function) – A Python function that specifies the constraint with a equality or inequality expression. The rule must hold at least two arguments: First the energy system instance it is added to (in most cases: self), second the ConcreteModel of the instance (model). Additional arguments represent sets (e.g., time).

  • name (str) – Name (identifier) of the added constraint. The rule name is used if no name is specified.
    Default: None

  • has_time_set (bool) – Is True if the time set of the energy system model is also a set of the added constraint.
    Default: True

  • alternative_set – Alternative constraint sets can be added here via iterable Python objects (e.g. list).
    Default: None

add_objective_function_contribution(rule, name=None)[source]

Additional objective function contributions can be added with this method. The method requires a Python function input that takes the main pyomo model (ConcreteModel: model) and returns a single (scalar) value.

Parameters
  • rule (function) – A Python function returning a scalar value which is added to the objective function of the model instance. The rule must hold exactly two arguments: The energy system instance it is added to (in most cases: self), second the ConcreteModel of the instance (model).

  • name (str) – Name (identifier) of the added objective function contribution. The rule name is used if no name is specified.
    Default: None

cluster(number_of_typical_periods=4, number_of_time_steps_per_period=24, cluster_method='hierarchical', **kwargs)[source]

Method for the aggregation and clustering of time series data. First, the time series data and their respective weights are collected from all components and split into pieces with equal length of ‘number_of_time_steps_per_period’. Subsequently, a clustering method is called and each period is assigned to one of ‘number_of_typical_periods’ typical periods. The clustered data is later stored in the components. The package tsam (time series aggregation module) is used to perform the clustering. The clustering algorithm can be controlled by adding required keyword arguments (using ‘kwargs’ parameter). To learn more about tsam and possible keyword arguments see the package documentation.

Parameters
  • number_of_typical_periods (int (>0)) – Number of typical periods to be clustered.
    Default: 4

  • number_of_time_steps_per_period (int (>0)) – Number of time steps per period
    Default: 24

  • cluster_method (str) – Name of the applied clustering method (e.g., ‘k_means’). See the tsam documentation for all possible options.
    Default: ‘hierarchical’

declare_time_sets(model, use_clustered_data)[source]

Initialize time parameters and four different time sets.

The “time_set” represents the general set. The index holds tuples of periods and time steps inside of these periods. In case the optimization is performed without time series aggregation, the set runs from [(0,0), (0,1), ..to.., (0,number_of_time_steps-1)]. Otherwise: [(0,0), …, (0,number_of_time_steps_per_period-1), (1,0), …, (number_of_typical_periods-1, number_of_time_steps_per_period-1)].
The set “intra_period_time_set” holds tuples of periods and points in time before, after or between regular time steps inside of a period. Hence, the second value runs from 0 to “number_of_time_steps” (without aggregation) or “number_of_time_steps_per_period” respectively.
The third set “inter_period_time_set” is one-dimensional and ranges from 0 to the overall number of periods plus 1 (1 + number_of_time_steps / number_of_time_steps_per_period). It is empty if no aggregation is used.
The “typical_periods_set” is a set ranging from 0 to the number of typical periods. If no aggregation is used it only holds 0.

E.g.: Case with 2 periods and 3 time steps per period
1) ______(0,0)___(0,1)___(0,2)___________(1,0)___(1,1)___(1,2)_____
2) __(0,0)___(0,1)___(0,2)___(0,3)___(1,0)___(1,1)___(1,2)___(1,3)_
3) 0___________________________ 1 __________________________2
4) ______________ 0 ___________________________ 1 _____________
1) time_set, 2) intra_period_time_steps_set, 3) inter_period_time_steps_set, 4) typical_periods_set

Parameters
  • model (pyomo ConcreteModel) – Pyomo model instance holding sets, variables, constraints and the objective function.

  • use_clustered_data (bool) – Declare optimization model with original (full scale) time series (=> False) or clustered data (=> True).

declare_objective(model)[source]

Method to declare the objective function of the optimization problem. The objective function contributions (CAPEX and OPEX) are calculated in the components itself, and collected and summarized by the ‘declare_objective’ function of the EnergySystem instance. The objective function of the optimization is the maximization of the net present value.

Parameters

model (pyomo ConcreteModel) – Pyomo model instance holding sets, variables, constraints and the objective function.

declare_model(use_clustered_data=False, declare_persistent=False, persistent_solver='gurobi_persistent')[source]

Declare the pyomo optimization model of the EnergySystem instance. First, all component connections are established by using their input and output specifications and the plausibility of connections is validated. Then, the ConcreteModel instance is created and time sets, component model blocks, variables, ports, constraints, arcs, and the objective function are added.

Parameters
  • use_clustered_data (bool) – Declare optimization model with original (full scale) time series (=> False) or clustered data (=> True).
    Default: False

  • declare_persistent (bool) – States if a persistent model instance should be formed. In this case, after model declaration a persistent solver instance is created and the declared model instance is assigned.
    Default: False

  • persistent_solver (str) – Name of the persistent solver to be used. Possible options are “gurobi_persistent” and “cplex_persistent”. Is ignored if keyword “declare_persistent” is False.
    Default: ‘gurobi_persistent’

optimize(declare_model=True, use_clustered_data=False, declare_persistent=False, persistent_solver='gurobi_persistent', solver='gurobi', time_limit=None, optimization_specs='', results_file='results.json', tee=True)[source]

Call the optimization routine for the EnergySystem instance. First, a new pyomo model instance is built (if ‘declare_model’=True), then the model is delivered to the specified solver and finally, the optimization results are exported to a json-file.

Parameters
  • declare_model (bool) – Declare a new instance of the pyomo ConcreteModel (=> True: Call function ‘declare_model’) or use a previously declared model instance if available (=> False).
    Default: True

  • use_clustered_data (bool) – Declare optimization model with original (full scale) time series (=> False) or clustered data (=> True).
    Default: False

  • declare_persistent (bool) – States if a persistent model instance should be formed. In this case, after model declaration a persistent solver instance is created and the declared model instance is assigned.
    Default: False

  • persistent_solver (str) – Name of the persistent solver to be used. Possible options are “gurobi_persistent” and “cplex_persistent”. Is ignored if keyword “declare_persistent” is False.
    Default: ‘gurobi_persistent’

  • solver (str) – Name of the applied solver (make sure the solver is available on your machine and aristopy can find the path to the solver executables).
    Default: ‘gurobi’

  • time_limit (int (>0) or None) – Limits the total optimization time (in seconds). If the time limit is reached, the solver returns with the best currently found solution. If None is specified, solver runs until the default time limit is exceeded (solver specific) or another criteria for abortion is triggered (e.g., reached ‘MIPGap’).
    Default: None

  • optimization_specs (str) – Additional solver parameters can be set from a string. To find out more about possible solver options check the documentation of the applied solver (e.g., see gurobi documentation)
    E.g.: ‘Threads=1 MIPGap=0.01’
    Default: ‘’

  • results_file (str or None) – Name of the results file (required format: .json).
    Default: ‘results.json’

  • tee (bool) – Show solver output (on screen and/or logfile).
    Default: True

export_component_configuration(write_to_excel=False, file_name='component_config.xlsx')[source]

This function collects the configuration data of all modeled components (results of the optimization) as pandas Series and returns them in a pandas DataFrame. The configuration features are (if exist):

  • the binary existence variable (utils.BI_EX),

  • the binary existence variables of modules (utils.BI_MODULE_EX)

  • the component capacity variable (utils.CAP)

Parameters
  • write_to_excel (bool) – Specify whether the component configuration DataFrame should be stored in an Excel-file.
    Default: False

  • file_name (str) – Name of the exported Excel-file containing the component configuration (if flag “write_to_excel” is True).
    Default: ‘component_config.xlsx’

Returns

The configuration of all components of the model instance.

Return type

pandas DataFrame

import_component_configuration(config, fix_existence=True, fix_modules=True, fix_capacity=True, store_previous_variables=True)[source]

Function to load a pandas DataFrame with configuration specifications (binary existence variables and capacity variable values) and fix the configuration of the modeled components accordingly.

Parameters
  • config (pandas DataFrame) – The component configuration of the model instance (generated by function ‘export_component_configuration’).

  • fix_existence (bool) – Specify whether the imported (global) binary component existence variables should be fixed (if available).
    Default: True

  • fix_modules (bool) – Specify whether the imported binary existence variables of the component modules should be fixed (if available).
    Default: True

  • fix_capacity (bool) – Specify whether the imported component capacity variable should be fixed or not.
    Default: True

  • store_previous_variables (bool) – State whether the representation of the variables before applying the configuration import should be stored in DataFrame “variables_copy” of each component. This representation can be used by function “reset_component_variables” to undo changes.
    Default: True

add_design_integer_cut_constraint(which_instances='all', include_existence=True, include_modules=True)[source]

Function to add an integer cut constraint to the Concrete Model of the EnergySystem instance. Hereby, the currently calculated design solution is excluded from the solution space. Hence, in a next optimization run of the same model instance a different design solution has to be determined. The integer cuts are destroyed once a new optimization model is declared.

Parameters
  • which_instances (str 'all' or list of component (group) names) – State which components should be considered while formulating the integer cut constraint. The argument can either take the string ‘all’ or a list of component (group) names.
    Default: ‘all’

  • include_existence (bool) – State if the binary existence variables of the components should be considered (if available) for formulating the integer cut constraint.
    Default: True

  • include_modules (bool) – State if the binary modules existence variables of the components should be considered (if available) for formulating the integer cut constraint.
    Default: True

relax_integrality(which_instances='all', include_existence=True, include_modules=True, include_time_dependent=True, store_previous_variables=True)[source]

Function to relax the integrality of the binary variables of the modelled components. This means binary variables are declared to be ‘NonNegativeReals with an upper bound of 1. The relaxation can be performed for the binary existence variable, the module existence binary variables and time-dependent binary variables.

Parameters
  • which_instances (str 'all' or list of component (group) names) – State for which components the relaxation of the binary variables should be done. The keyword argument can either take the string ‘all’ or a list of component (group) names.
    Default: ‘all’

  • include_existence (bool) – State whether the integrality of the binary existence variables should be relaxed (if available).
    Default: True

  • include_modules (bool) – State whether the integrality of the binary modules existence variables should be relaxed (if available).
    Default: True

  • include_time_dependent (bool) – State whether the integrality of the time-dependent binary variables should be relaxed. (if available).
    Default: True

  • store_previous_variables (bool) – State whether the representation of the variables before applying the relaxation should be stored in the DataFrame “variables_copy” of each component. This representation can be used by function “reset_component_variables” to undo changes.
    Default: True

edit_component_variables(name, which_instances='all', store_previous_variables=True, **kwargs)[source]

Method for manipulating the specifications of already defined component variables (e.g., change variable domain, add variable bounds, etc.).

Parameters
  • name (str) – Name / identifier of the edited variable.

  • which_instances (str 'all' or list of component (group) names) – State for which components the relaxation of the binary variables should be done. The keyword argument can either take the string ‘all’ or a list of component (group) names.
    Default: ‘all’

  • store_previous_variables (bool) – State whether the representation of the variables before applying the relaxation should be stored in the DataFrame “variables_copy” of each component. This representation can be used by function “reset_component_variables” to undo changes.
    Default: True

  • kwargs – Additional keyword arguments for editing. Options are: ‘ub’ and ‘lb’ to add an upper or lower variable bound, ‘domain’ to set the variable domain, and ‘has_time_set’ to define if the variable should inherit the global time set of the EnergySystem.

reset_component_variables(which_instances='all')[source]

Function to reset the variables of the modeled components to their state that is stored in the component DataFrame “variables_copy”. This includes the resetting of the DataFrame “variables” and the pyomo variables itself (if constructed).

Parameters

which_instances (str 'all' or list of component (group) names) – State for which components the variable resetting should be done. The keyword argument can either take the string ‘all’ or a list of component (group) names.
Default: ‘all’

serialize()[source]

This method collects all relevant input data and optimization results from the EnergySystem instance, the added components and the pyomo model instance. The data is arranged in an ordered dictionary, that is later exported as a file in JSON-format.

Returns

OrderedDict