Source code for tessif_examples.specialized.self_similar_system_model

# src/tessif_examples/self_similar_system_model.py
"""Tessif minimum working example energy system model."""
import datetime
import random

import tessif.frused.namedtuples as nts
from pandas import date_range
from tessif import components, system_model


[docs]def create_self_similar_system_model(n=1, timeframe=None, unit="minimal", **kwargs): """Create a self similar system model. Created by Mathias Ammon, Frederik Emmel and Andreas Jessen. This energy system is obtained by repeating its unit N times. The singular units are connected to each other through their central bus. Meaning the central bus of energy system N is connected to the central bus of energy system N-1 via a :class:`~tessif.model.components.Connector` object. Parameters ---------- N: int Number of units the self similar energy system consists of. timeframe: pandas.DatetimeIndex Datetime index representing the evaluated timeframe. Explicitly stating: - initial datatime (0th element of the :class:`pandas.DatetimeIndex`) - number of time steps (length of :class:`pandas.DatetimeIndex`) - temporal resolution (:attr:`pandas.DatetimeIndex.freq`) For example:: idx = pd.DatetimeIndex( data=pd.date_range( '2016-01-01 00:00:00', periods=11, freq='H')) unit: str Specify which of tessif's hardcoded examples should be used as unit of the self similar energy system. Currently available are: - 'minimal': Uses _create_minimal_es_unit() which is the smallest unit available. - 'component': Uses _create_component_es_unit() which is based on create_component_es(). - 'grid': Uses _create_grid_es_unit() which is based on create_transcne_es(). - 'hamburg': Uses _create_hhes_unit() which is based on create_hhes_unit(). kwargs: Are passed to the _create_[...]_unit() function. """ if timeframe is None: timeframe = date_range(datetime.datetime.now().date(), periods=5, freq="H") # Create the energy system using tessif fractals = list() for nmbr in range(n): # the n-th energy system starting to count at 0 is added to the list of # es units. if unit == "minimal": fractals.append( create_minimal_es_unit(n=nmbr, timeframe=timeframe, **kwargs) ) # elif unit == 'component': # fractals.append( # _create_component_es_unit(n=n, timeframe=timeframe, **kwargs)) # elif unit == 'grid': # fractals.append(_create_grid_es_unit( # n=n, timeframe=timeframe, **kwargs)) # elif unit == 'hamburg': # fractals.append(_create_hhes_unit( # n=n, timeframe=timeframe, **kwargs)) self_similar_es = system_model.AbstractEnergySystem( uid=f"Self Similar System Model (n={n})", busses=[bus for fractal in fractals for bus in fractal.busses], sinks=[sink for fractal in fractals for sink in fractal.sinks], sources=[source for fractal in fractals for source in fractal.sources], connectors=[ connector for fractal in fractals for connector in fractal.connectors ], transformers=[ transformer for fractal in fractals for transformer in fractal.transformers ], storages=[storage for fractal in fractals for storage in fractal.storages], timeframe=timeframe, ) return self_similar_es
[docs]def create_minimal_es_unit(n, timeframe=None, seed=None): """Create a minimal self simular energy system unit. Is used by create_self_similar_energy_system(). Created by Mathias Ammon and Andreas Jessen. The self similar energy system unit consists of: - 3 :class:`~tessif.components.Source` objects: - One having a randomized output, emulating renewable sources. With an installed power between 10 and 200 units. - One `slack source <https://en.wikipedia.org/wiki/Slack_bus>`_ providing energy to balance the system if needed. (This could be interpreted as an import node, for meeting load demands) - One commodity source feeding the transformer - 2 :class:`~tessif.components.Sink` objects: - One having a fixed input with a net demand between 50 and 100 units. - One `slack sink <https://en.wikipedia.org/wiki/Slack_bus>`_ taking energy in to balance the system if needed. (This could be interpreted as an export node, for handling excess loads.) - 2 :class:`~tessif.components.Bus` objects: - One central bus connecting the storage and transformer, as well as the sinks and sources and up to 2 additional self similar energy system units. - An auxiliary bus connecting the transformer and the central bus - 1 :class:`~tessif.components.Transformer` object: - Fully parameterized transformer emulating a coal power plant with an installed capacity between 50 and 100 units. - 1 :class:`~tessif.components.Storage` object: - no constraints to in and outflow. Efficiency, losses, expansion investment etc. oriented at grid level batteries (e.g. tesla) Parameters ---------- n: int Number of the es unit. This ist needed to be able to give each component in the complete self similar es a unique name. timeframe: pandas.DatetimeIndex Datetime index representing the evaluated timeframe. Explicitly stating: - initial datatime (0th element of the :class:`pandas.DatetimeIndex`) - number of time steps (length of :class:`pandas.DatetimeIndex`) - temporal resolution (:attr:`pandas.DatetimeIndex.freq`) For example:: idx = pd.DatetimeIndex( data=pd.date_range( '2016-01-01 00:00:00', periods=11, freq='H')) """ if timeframe is None: timeframe = date_range( datetime.datetime.now(), periods=5, freq="H", ) # See tessif.examples.data.tsf.py_hard as well as # tessif.components for examples and information # (both in the code and using the doc) # 1) randomize demand and production if seed: random.seed(seed) demand = random.randint(1, 100) renewable_output = random.randint(1, 50) demand_sink = components.Sink( name="Sink " + str(n), inputs=("electricity",), flow_rates={"electricity": nts.MinMax(min=demand, max=demand)}, ) # excess_sink enables the energy system to be always solvable even if # the randomized components wouldn't provide a solvable energy system. excess_sink = components.Sink( name="Excess Sink " + str(n), inputs=("electricity",), flow_costs={"electricity": 100}, ) # 2) Create the sources excess_source = components.Source( name="Excess Source " + str(n), outputs=("electricity",), flow_costs={"electricity": 100}, ) # 2.1) renewable source renewable_source = components.Source( name="Renewable Source " + str(n), outputs=("electricity",), flow_costs={"electricity": 5}, node_type="Renewable", carrier="Electricity", flow_rates={ "electricity": nts.MinMax(min=renewable_output, max=renewable_output) }, flow_emissions={"electricity": 0}, ) # 2.2) non-renewable source non_renewable_source = components.Source( name="Non Renewable Source " + str(n), outputs=("fuel",), flow_costs={"fuel": 10}, ) # 3) Create the transformer power_generator = components.Transformer( name="Power Generator " + str(n), inputs=("fuel",), outputs=("electricity",), conversions={("fuel", "electricity"): 0.42}, ) # 4) Create the connector. (Use connectors list to prevent error in case no # connector is created.) connectors = list() if n == 0: pass else: connector = components.Connector( name="Connector " + str(n), interfaces=( "Central Bus " + str(n - 1), "Central Bus " + str(n), ), inputs=[ "Central Bus " + str(n - 1), "Central Bus " + str(n), ], outputs=( "Central Bus " + str(n - 1), "Central Bus " + str(n), ), ) connectors.append(connector) # 5) Create the storage storage = components.Storage( name="Storage " + str(n), input="electricity", output="electricity", capacity=1, initial_soc=1, ) # 6) Create the bus central_bus = components.Bus( name="Central Bus " + str(n), inputs=( "Excess Source " + str(n) + ".electricity", "Storage " + str(n) + ".electricity", "Renewable Source " + str(n) + ".electricity", "Power Generator " + str(n) + ".electricity", ), outputs=( "Excess Sink " + str(n) + ".electricity", "Sink " + str(n) + ".electricity", "Storage " + str(n) + ".electricity", ), ) # There needs to be another bus which connects the transformer and the # non-renewable source. fuel_line = components.Bus( name="Fuel Line " + str(n), inputs=("Non Renewable Source " + str(n) + ".fuel",), outputs=("Power Generator " + str(n) + ".fuel",), ) minimal_es = system_model.AbstractEnergySystem( uid="Minimum Self Similar System Model Unit " + str(n), busses=(central_bus, fuel_line), sinks=(demand_sink, excess_sink), sources=(excess_source, non_renewable_source, renewable_source), connectors=connectors, transformers=(power_generator,), storages=(storage,), timeframe=timeframe, ) return minimal_es