Source code for aristopy.bus

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ==============================================================================
#    B U S
# ==============================================================================
"""
* File name: bus.py
* Last edited: 2020-06-14
* Created by: Stefan Bruche (TU Berlin)

A Bus component collects and transfers a commodity. Bus components can also
be used to model transmission lines between different sites.
"""
import pyomo.environ as pyo
from aristopy import utils
from aristopy.component import Component


[docs]class Bus(Component): def __init__(self, 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, capex_per_capacity=0, capex_if_exist=0, opex_per_capacity=0, opex_if_exist=0, opex_operation=0, losses=0 ): """ Initialize an instance of the Bus class. .. note:: See the documentation of the :class:`Component <aristopy.component.Component>` class for a description of all keyword arguments and inherited methods. :param losses: Factor to specify the relative loss of the transported commodity between inlet and outlet per hour of operation (0 => no loss; 1 => 100% loss). |br| *Default: 0* :type losses: float or int (0<=value<=1) """ # Prevent None at inlet & outlet! (Flows are checked in Component init) if inlet is None: raise utils.io_error_message('Bus', name, 'inlet') if outlet is None: raise utils.io_error_message('Bus', name, 'outlet') Component.__init__(self, ensys=ensys, name=name, inlet=inlet, outlet=outlet, basic_variable=basic_variable, has_existence_binary_var=has_existence_binary_var, time_series_data=time_series_data, scalar_params=scalar_params, additional_vars=additional_vars, user_expressions=user_expressions, capacity=capacity, capacity_min=capacity_min, capacity_max=capacity_max, capex_per_capacity=capex_per_capacity, capex_if_exist=capex_if_exist, opex_per_capacity=opex_per_capacity, opex_if_exist=opex_if_exist, opex_operation=opex_operation ) # Check and set additional input arguments self.losses = utils.check_and_set_range_zero_one(losses, 'losses') # Store the names for the loading and unloading variables self.inlet_variable = self.inlet[0].var_name self.outlet_variable = self.outlet[0].var_name # Last step: Add the component to the EnergySystem instance self.add_to_energy_system(ensys, name) def __repr__(self): return '<Bus: "%s">' % self.name # ========================================================================== # C O N V E N T I O N A L C O N S T R A I N T D E C L A R A T I O N # ==========================================================================
[docs] def declare_component_constraints(self, ensys, model): """ Method to declare all component constraints. The following constraint methods are inherited from the Component class and are not documented in this sub-class: * :meth:`con_couple_bi_ex_and_cap <aristopy.component.Component.con_couple_bi_ex_and_cap>` * :meth:`con_cap_min <aristopy.component.Component.con_cap_min>` *Method is not intended for public access!* :param ensys: Instance of the EnergySystem class :param model: Pyomo ConcreteModel of the EnergySystem instance """ # Time-independent constraints : # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.con_couple_bi_ex_and_cap() self.con_cap_min() # Time-dependent constraints : # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.con_operation_limit(model) self.con_bus_balance(model)
# ************************************************************************** # Time-dependent constraints # **************************************************************************
[docs] def con_operation_limit(self, model): """ The basic variable of a component is limited by its nominal capacity. This means, the operation (commodity at inlet or outlet) of a bus (MWh) is limited by its nominal power (MW) multiplied with the number of hours per time step. E.g.: |br| ``Q_IN[p, t] <= CAP * dt`` *Method is not intended for public access!* """ # Only required if component has a capacity variable if self.has_capacity_var: cap = self.variables[utils.CAP]['pyomo'] basic_var = self.variables[self.basic_variable]['pyomo'] dt = self.ensys.hours_per_time_step def con_operation_limit(m, p, t): return basic_var[p, t] <= cap * dt setattr(self.block, 'con_operation_limit', pyo.Constraint( model.time_set, rule=con_operation_limit))
[docs] def con_bus_balance(self, model): """ The quantity of the commodity at the outlet must equal the quantity at the inlet minus the the transmission loss share. A bus component cannot store a commodity (correction with "hours_per_time_step" not needed). E.g.: |br| ``Q_OUT[p, t] == Q_IN[p, t] * (1 - losses)`` *Method is not intended for public access!* """ inlet_var = self.variables[self.inlet_variable]['pyomo'] outlet_var = self.variables[self.outlet_variable]['pyomo'] def con_bus_balance(m, p, t): return outlet_var[p, t] == inlet_var[p, t] * (1 - self.losses) setattr(self.block, 'con_bus_balance', pyo.Constraint( model.time_set, rule=con_bus_balance))
# ========================================================================== # S E R I A L I Z E # ==========================================================================
[docs] def serialize(self): """ This method collects all relevant input data and optimization results from the Component instance, and returns them in an ordered dictionary. :return: OrderedDict """ comp_dict = super().serialize() comp_dict['inlet_variable'] = self.inlet_variable comp_dict['outlet_variable'] = self.outlet_variable return comp_dict