# tessif/examples/application/calliope_integration_scenarios.py
# -*- coding: utf-8 -*-
"""
:mod:`~tessif.examples.application.calliope_integration_scenarios` is a :mod:`tessif`
module aggregating the research results of a master thesis titled
**Comparison of modelling tools to optimize energy systems via integration into
an existing framework for transforming energy system models**
conducted by Max Reimer.
"""
# 1. Import the needed packages:
import os
import numpy as np
import pandas as pd
import tessif.frused.namedtuples as nts
from tessif.frused.paths import example_dir
from tessif.model import components, energy_system
[docs]def create_sources_example():
"""
Create a small energy system utilizing two emisison free and
expandable sources, as well as an emitting one.
This small energy system was used to analyse the implementation of tessif
sources, busses and demands in calliope as well as compare it to fine, oemof and pypsa.
It is the same as the create_expansion_plan_example in :mod:`~tessif.examples.data.tsf.py_hard`
Return
------
es: :class:`tessif.model.energy_system.AbstractEnergySystem`
Tessif energy system.
Examples
--------
Use :func:`create_expansion_plan_example` to quickly access a tessif
energy system to use for doctesting, or trying out this framework's
utilities.
>>> import tessif.examples.application.calliope_integration_scenarios as examples
>>> import matplotlib.pyplot as plt
>>> import tessif.visualize.nxgrph as nxv
>>> es = examples.create_sources_example()
>>> grph = es.to_nxgrph()
>>> drawing_data = nxv.draw_graph(
... grph,
... node_color={'Powerline': '#009900',
... 'Emitting Source': '#cc0033',
... 'Demand': '#00ccff',
... 'Capped Renewable': '#ffD700',
... 'Uncapped Renewable': '#ffD700',},
... node_size={'Powerline': 5000},
... layout='dot')
>>> # plt.show() # commented out for simpler doctesting
.. image:: ../data/images/expansion_plan_example.png
:align: center
:alt: Image showing the expansion plan example energy system graph.
"""
# 2. Create a simulation time frame of 2 one hour time steps as a
# :class:`pandas.DatetimeIndex`:
timeframe = pd.date_range('7/13/1990', periods=4, freq='H')
# 3. Creating the individual energy system components:
# emitting source having no costs and no flow constraints but emissions
emitting_source = components.Source(
name='Emitting Source',
outputs=('electricity',),
# Minimum number of arguments required
flow_emissions={
'electricity': 1
},
)
# capped source having no costs, no emission, no flow constraints
# but existing and max installed capacity (for expansion) as well
# as expansion costs
capped_renewable = components.Source(
name='Capped Renewable',
outputs=('electricity',),
# Minimum number of arguments required
flow_rates={'electricity': nts.MinMax(min=1, max=2)},
flow_costs={'electricity': 2, },
expandable={'electricity': True},
expansion_costs={'electricity': 1},
expansion_limits={'electricity': nts.MinMax(min=1, max=4)},
)
# uncapped source having no costs and no emissions
# but an externally set timeseries as well as expansion costs
uncapped_min, uncapped_max = [1, 2, 3, 1], [1, 2, 3, 1]
uncapped_renewable = components.Source(
name='Uncapped Renewable',
outputs=('electricity',),
# Minimum number of arguments required
# flow_rates={'electricity': nts.MinMax(min=0, max=1)},
flow_costs={'electricity': 2, },
expandable={'electricity': True},
expansion_costs={'electricity': 2},
timeseries={
'electricity': nts.MinMax(
min=uncapped_min,
max=uncapped_max
)
},
expansion_limits={
'electricity': nts.MinMax(
min=max(uncapped_max),
max=float('+inf'),
)
},
)
electricity_line = components.Bus(
name='Powerline',
inputs=(
'Emitting Source.electricity',
'Capped Renewable.electricity',
'Uncapped Renewable.electricity'),
outputs=('Demand.electricity',),
# Minimum number of arguments required
)
demand = components.Sink(
name='Demand',
inputs=('electricity',),
# Minimum number of arguments required
flow_rates={'electricity': nts.MinMax(min=10, max=10)},
)
global_constraints = {'emissions': 20}
# 4. Creating the actual energy system:
explicit_es = energy_system.AbstractEnergySystem(
uid='Sources_Example', # adjusted
busses=(electricity_line,),
sinks=(demand,),
sources=(
emitting_source,
capped_renewable,
uncapped_renewable,
),
timeframe=timeframe,
global_constraints=global_constraints,
)
return explicit_es
[docs]def create_storage_example():
"""
Create a small energy system utilizing an expandable storage with a fixed
capacity to outflow ratio.
This small energy system was used to analyse the implementation of tessif
storages in calliope as well as compare it to fine, oemof and pypsa.
It is an adjusted model following the create_storage_fixed_ratio_expansion_example
in :mod:`~tessif.examples.data.tsf.py_hard`
Return
------
es: :class:`tessif.model.energy_system.AbstractEnergySystem`
Tessif energy system.
Note
----
Calliope does not differ between input and outpuf efficiency, while the other tools do.
Since this difference is already known analysing this is not needed anymore, hence the
in and output efficiencies are set to be the same to find out unknown differences.
Examples
--------
Using :func:`create_storage_example` to quickly access a tessif energy
system to use for doctesting, or trying out this frameworks utilities.
>>> import tessif.examples.application.calliope_integration_scenarios as examples
>>> import matplotlib.pyplot as plt
>>> import tessif.visualize.nxgrph as nxv
>>> tsf_es = examples.create_storage_example()
>>> grph = tsf_es.to_nxgrph()
>>> drawing_data = nxv.draw_graph(
... grph,
... node_color={'Powerline': '#009900',
... 'Storage': '#cc0033',
... 'Demand': '#00ccff',
... 'Generator': '#ffD700',},
... node_size={'Storage': 5000},
... layout='neato')
>>> # plt.show() # commented out for simpler doctesting
.. image:: ../data/images/storage_es_example.png
:align: center
:alt: Image showing the create_storage_example energy system graph.
"""
timeframe = pd.date_range('7/13/1990', periods=5, freq='H')
demand = components.Sink(
name='Demand',
inputs=('electricity',),
carrier='electricity',
node_type='sink',
flow_rates={'electricity': nts.MinMax(min=0, max=10)},
timeseries={
'electricity': nts.MinMax(
min=np.array([10, 10, 7, 5, 10]), # adjusted
max=np.array([10, 10, 7, 5, 10]) # adjusted
)
}
)
generator = components.Source(
name='Generator',
outputs=('electricity',),
carrier='electricity',
node_type='source',
flow_rates={'electricity': nts.MinMax(min=0, max=10)},
flow_costs={'electricity': 0},
timeseries={
'electricity': nts.MinMax(
min=np.array([19, 19, 19, 0, 0]),
max=np.array([19, 19, 19, 0, 0])
)
}
)
powerline = components.Bus(
name='Powerline',
inputs=('Generator.electricity', 'Storage.electricity'),
outputs=('Demand.electricity', 'Storage.electricity',),
carrier='electricity',
node_type='bus',
)
storage = components.Storage(
name='Storage',
input='electricity',
output='electricity',
capacity=1,
initial_soc=0.5, # new
carrier='electricity',
node_type='storage',
idle_changes=nts.PositiveNegative(positive=0, negative=0.01), # new
flow_rates={'electricity': nts.MinMax(min=0, max=0.1)},
flow_efficiencies={
'electricity': nts.InOut(inflow=0.9, outflow=0.9)}, # adjusted
flow_costs={'electricity': 1},
flow_emissions={'electricity': 0.5},
expandable={'capacity': True, 'electricity': True},
fixed_expansion_ratios={'electricity': True},
expansion_costs={'capacity': 2, 'electricity': 0},
expansion_limits={
'capacity': nts.MinMax(min=1, max=float('+inf')),
'electricity': nts.MinMax(min=0.1, max=float('+inf'))},
)
storage_es = energy_system.AbstractEnergySystem(
uid='Storage_Example', # adjusted
busses=(powerline,),
sinks=(demand,),
sources=(generator,),
storages=(storage,),
timeframe=timeframe
)
return storage_es
[docs]def create_chp_example():
"""
Create a small energy system using :mod:`tessif's
model <tessif.model>` optimizing it for costs to demonstrate
a chp application.
This small energy system was used to analyse the implementation of tessif
multi output transformer in calliope as well as compare it to fine, oemof and pypsa.
It is an adjusted model following the create_chp
in :mod:`~tessif.examples.data.tsf.py_hard`
Return
------
es: :class:`tessif.model.energy_system.AbstractEnergySystem`
Tessif energy system.
Examples
--------
Using :func:`create_chp` to quickly access a tessif energy system
to use for doctesting, or trying out this frameworks utilities.
>>> import tessif.examples.application.calliope_integration_scenarios as examples
>>> import matplotlib.pyplot as plt
>>> import tessif.visualize.nxgrph as nxv
>>> tsf_es = examples.create_chp_example()
>>> grph = tsf_es.to_nxgrph()
>>> drawing_data = nxv.draw_graph(
... grph,
... node_color={
... 'Gas Source': '#669999',
... 'Gas Grid': '#669999',
... 'CHP': '#6633cc',
... 'Backup Heat': 'red',
... 'Heat Grid': 'red',
... 'Heat Demand': 'red',
... 'Backup Power': 'yellow',
... 'Powerline': 'yellow',
... 'Power Demand': 'yellow',
... },
... )
>>> # plt.show() # commented out for simpler doctesting
.. image:: ../transformation/auto_comparison/chp_graph.png
:align: center
:alt: Image showing analyzed chp graph.
"""
# 2. Create a simulation time frame of four one-hour timesteps as a
# :class:`pandas.DatetimeIndex`:
timeframe = pd.date_range('7/13/1990', periods=4, freq='H')
global_constraints = {'emissions': float('+inf')}
# 3. Creating the individual energy system components:
gas_supply = components.Source(
name='Gas Source',
outputs=('gas',),
# Minimum number of arguments required
)
gas_grid = components.Bus(
name='Gas Grid',
inputs=('Gas Source.gas', ),
outputs=('CHP.gas',),
# Minimum number of arguments required
)
# conventional power supply is cheaper, but has emissions allocated to it
chp = components.Transformer(
name='CHP',
inputs=('gas',),
outputs=('electricity', 'heat'),
conversions={
('gas', 'electricity'): 0.3,
('gas', 'heat'): 0.2,
},
flow_rates={
'gas': nts.MinMax(min=0, max=float('+inf')), # new
'electricity': nts.MinMax(min=0, max=3), # new
'heat': nts.MinMax(min=0, max=2)}, # new
flow_costs={'electricity': 3, 'heat': 2, 'gas': 0},
flow_emissions={'electricity': 2, 'heat': 3, 'gas': 0},
expandable={'gas': False, 'electricity': True, 'heat': True}, # new
expansion_costs={'gas': 0, 'electricity': 2, 'heat': 1}, # new
expansion_limits={
'gas': nts.MinMax(min=0, max=float('+inf')), # new
'electricity': nts.MinMax(min=3, max=float('+inf')), # new
'heat': nts.MinMax(min=2, max=float('+inf'))}, # new
)
# back up power, expensive
backup_power = components.Source(
name='Backup Power',
outputs=('electricity',),
flow_costs={'electricity': 100}, # adjusted
)
# Power demand needing 10 energy units per time step
power_demand = components.Sink(
name='Power Demand',
inputs=('electricity',),
# Minimum number of arguments required
flow_rates={'electricity': nts.MinMax(min=10, max=10)},
)
power_line = components.Bus(
name='Powerline',
inputs=('Backup Power.electricity', 'CHP.electricity'),
outputs=('Power Demand.electricity',),
# Minimum number of arguments required
)
# Back up heat source, expensive
backup_heat = components.Source(
name='Backup Heat',
outputs=('heat',),
flow_costs={'heat': 100}, # adjusted
)
# Heat demand needing 10 energy units per time step
heat_demand = components.Sink(
name='Heat Demand',
inputs=('heat',),
# Minimum number of arguments required
flow_rates={'heat': nts.MinMax(min=10, max=10)},
)
heat_grid = components.Bus(
name='Heat Grid',
inputs=('CHP.heat', 'Backup Heat.heat'),
outputs=('Heat Demand.heat',),
# Minimum number of arguments required
)
# 4. Creating the actual energy system:
explicit_es = energy_system.AbstractEnergySystem(
uid='CHP_Example',
busses=(gas_grid, power_line, heat_grid),
sinks=(power_demand, heat_demand),
sources=(gas_supply, backup_power, backup_heat),
transformers=(chp,),
timeframe=timeframe,
global_constraints=global_constraints,
)
return explicit_es
[docs]def create_connector_example():
"""
Create a small energy system using :mod:`tessif's
model <tessif.model>` optimizing it for costs to demonstrate
a connector.
This small energy system was used to analyse the implementation of tessif
connector in calliope as well as compare it to fine, oemof and pypsa.
It is an the same model as the create_connected_es
in :mod:`~tessif.examples.data.tsf.py_hard`
Return
------
es: :class:`tessif.model.energy_system.AbstractEnergySystem`
Tessif energy system.
Examples
--------
Using :func:`create_connected_es` to quickly access a tessif energy system
to use for doctesting, or trying out this frameworks utilities:
>>> import tessif.examples.application.calliope_integration_scenarios as examples
>>> import matplotlib.pyplot as plt
>>> import tessif.visualize.nxgrph as nxv
>>> es = examples.create_connector_example()
>>> grph = es.to_nxgrph()
>>> drawing_data = nxv.draw_graph(
... grph,
... node_color={'connector': '#9999ff',
... 'bus-01': '#cc0033',
... 'bus-02': '#00ccff'},
... node_size={'connector': 5000},
... layout='neato')
>>> # plt.show() # commented out for simpler doctesting
.. image:: ../data/images/connected_es_example.png
:align: center
:alt: alternate text
"""
timeframe = pd.date_range('7/13/1990', periods=3, freq='H')
s1 = components.Sink(
name='sink-01',
inputs=('electricity',),
flow_rates={'electricity': nts.MinMax(min=0, max=15)},
timeseries={'electricity': nts.MinMax(
min=np.array([0, 15, 10]), max=np.array([0, 15, 10]))})
so1 = components.Source(
name='source-01',
outputs=('electricity',),
flow_rates={'electricity': nts.MinMax(min=0, max=10)},
flow_costs={'electricity': 1},
flow_emissions={'electricity': 0.8})
mb1 = components.Bus(
name='bus-01',
inputs=('source-01.electricity',),
outputs=('sink-01.electricity',),
)
s2 = components.Sink(
name='sink-02',
inputs=('electricity',),
flow_rates={'electricity': nts.MinMax(min=0, max=15)},
timeseries={'electricity': nts.MinMax(
min=np.array([15, 0, 10]), max=np.array([15, 0, 10]))})
so2 = components.Source(
name='source-02',
outputs=('electricity',),
flow_rates={'electricity': nts.MinMax(min=0, max=10)},
flow_costs={'electricity': 1},
flow_emissions={'electricity': 1.2})
mb2 = components.Bus(
name='bus-02',
inputs=('source-02.electricity',),
outputs=('sink-02.electricity',),
)
c = components.Connector(
name='connector',
interfaces=('bus-01', 'bus-02'),
conversions={('bus-01', 'bus-02'): 0.9,
('bus-02', 'bus-01'): 0.8})
connected_es = energy_system.AbstractEnergySystem(
uid='Connector_Example', # adjusted
busses=(mb1, mb2),
sinks=(s1, s2,),
sources=(so1, so2),
connectors=(c,),
timeframe=timeframe
)
return connected_es
[docs]def create_component_example(
expansion_problem=False, periods=8760,):
"""
Create a model of a generic component based energy system using
:mod:`tessif's model <tessif.model>`.
This energy system was used to compare calliope to fine, oemof and pypsa in a
bigger example for the timeframe of a year in hourly resolution.
It is an the same model as the create_component_es
in :mod:`~tessif.examples.data.tsf.py_hard`
Parameters
----------
expansion_problem : bool, default=False
Boolean which states whether a commitment problem (False)
or expansion problem (True) is to be solved
periods : int, default=3
Number of time steps of the evaluated timeframe
(one time step is one hour)
Return
------
es: :class:`tessif.model.energy_system.AbstractEnergySystem`
Tessif energy system.
Examples
--------
Use :func:`create_component_es` to quickly access a tessif energy system
to use for doctesting, or trying out this framework's utilities.
>>> import tessif.examples.application.calliope_integration_scenarios as examples
>>> import matplotlib.pyplot as plt
>>> import tessif.visualize.nxgrph as nxv
>>> es = examples.create_component_example()
>>> grph = es.to_nxgrph()
>>> drawing_data = nxv.draw_graph(
... grph,
... node_color={
... 'Hard Coal Supply': '#666666',
... 'Hard Coal Supply Line': '#666666',
... 'Hard Coal PP': '#666666',
... 'Hard Coal CHP': '#666666',
... 'Solar Panel': '#FF7700',
... 'Heat Storage': '#cc0033',
... 'Heat Demand': 'Red',
... 'Heat Plant': '#cc0033',
... 'Heatline': 'Red',
... 'Power To Heat': '#cc0033',
... 'Biogas CHP': '#006600',
... 'Biogas Line': '#006600',
... 'Biogas Supply': '#006600',
... 'Onshore Wind Turbine': '#99ccff',
... 'Offshore Wind Turbine': '#00ccff',
... 'Gas Station': '#336666',
... 'Gas Line': '#336666',
... 'Combined Cycle PP': '#336666',
... 'El Demand': '#ffe34d',
... 'Battery': '#ffe34d',
... 'Powerline': '#ffcc00',
... 'Lignite Supply': '#993300',
... 'Lignite Supply Line': '#993300',
... 'Lignite Power Plant': '#993300',
... },
... node_size={
... 'Powerline': 5000,
... 'Heatline': 5000
... },
... title='Component Based Example Energy System Graph',
... )
>>> # plt.show() # commented out for simpler doctesting
.. image:: ../data/images/component_es_example.png
:align: center
:alt: Image showing the create_component_es energy system graph.
"""
# Create a simulation time frame
timeframe = pd.date_range('1/1/2019', periods=periods, freq='H')
# Initiate the global constraints depending on the scenario
if expansion_problem is False:
use_case = 'commitment' # new
global_constraints = {
'name': 'Commitment_Scenario',
'emissions': float('+inf'),
}
else:
use_case = 'expansion' # new
global_constraints = {
'name': 'Expansion_Scenario',
'emissions': 250000,
}
# Variables for timeseries of fluctuate wind, solar and demand
csv_data = pd.read_csv(os.path.join(example_dir, 'data', 'tsf', 'load_profiles',
'component_scenario_profiles.csv'), index_col=0, sep=';')
# solar:
pv = csv_data['pv'].values.flatten()[0:periods]
# scale relative values with the installed pv power
pv = pv * 1100
# wind onshore:
wind_onshore = csv_data['wind_on'].values.flatten()[0:periods]
# scale relative values with installed onshore power
wind_onshore = wind_onshore * 1100
# wind offshore:
wind_offshore = csv_data['wind_off'].values.flatten()[0:periods]
# scale relative values with installed offshore power
wind_offshore = wind_offshore * 150
# electricity demand:
el_demand = csv_data['el_demand'].values.flatten()[0:periods]
max_el = np.max(el_demand)
# heat demand:
th_demand = csv_data['th_demand'].values.flatten()[0:periods]
max_th = np.max(th_demand)
# Creating the individual energy system components:
# ---------------- Sources (incl wind and solar) -----------------------
hard_coal_supply = components.Source(
name='Hard Coal Supply',
outputs=('Hard_Coal',),
sector='Power',
carrier='Hard_Coal',
node_type='source',
accumulated_amounts={
'Hard_Coal': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'Hard_Coal': nts.MinMax(min=0, max=float('+inf'))},
flow_costs={'Hard_Coal': 0},
flow_emissions={'Hard_Coal': 0},
flow_gradients={
'Hard_Coal': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'Hard_Coal': nts.PositiveNegative(
positive=0, negative=0)},
timeseries=None,
expandable={'Hard_Coal': False},
expansion_costs={'Hard_Coal': 0},
expansion_limits={'Hard_Coal': nts.MinMax(min=0, max=float('+inf'))},
)
lignite_supply = components.Source(
name='Lignite Supply',
outputs=('lignite',),
sector='Power',
carrier='Lignite',
node_type='source',
accumulated_amounts={
'lignite': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'lignite': nts.MinMax(min=0, max=float('+inf'))},
flow_costs={'lignite': 0},
flow_emissions={'lignite': 0},
flow_gradients={
'lignite': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'lignite': nts.PositiveNegative(
positive=0, negative=0)},
timeseries=None,
expandable={'lignite': False},
expansion_costs={'lignite': 0},
expansion_limits={'lignite': nts.MinMax(min=0, max=float('+inf'))},
)
fuel_supply = components.Source(
name='Gas Station',
outputs=('fuel',),
sector='Power',
carrier='Gas',
node_type='source',
accumulated_amounts={
'fuel': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'fuel': nts.MinMax(min=0, max=float('+inf'))},
flow_costs={'fuel': 0},
flow_emissions={'fuel': 0},
flow_gradients={
'fuel': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'fuel': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'fuel': False},
expansion_costs={'fuel': 0},
expansion_limits={'fuel': nts.MinMax(min=0, max=float('+inf'))},
)
biogas_supply = components.Source(
name='Biogas Supply',
outputs=('biogas',),
sector='Power',
carrier='Biogas',
node_type='source',
accumulated_amounts={
'biogas': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'biogas': nts.MinMax(min=0, max=float('+inf'))},
flow_costs={'biogas': 0},
flow_emissions={'biogas': 0},
flow_gradients={
'biogas': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'biogas': nts.PositiveNegative(
positive=0, negative=0)},
timeseries=None,
expandable={'biogas': False},
expansion_costs={'biogas': 0},
expansion_limits={'biogas': nts.MinMax(min=0, max=float('+inf'))},
)
solar_panel = components.Source(
name='Solar Panel',
outputs=('electricity',),
sector='Power',
carrier='electricity',
node_type='Renewable',
accumulated_amounts={
'electricity': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'electricity': nts.MinMax(min=0, max=1100)},
flow_costs={'electricity': 80},
flow_emissions={'electricity': 0.05},
flow_gradients={
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'electricity': nts.PositiveNegative(
positive=0, negative=0)},
timeseries={'electricity': nts.MinMax(
min=np.array(periods * [0]),
max=np.array(pv))},
expandable={'electricity': expansion_problem},
expansion_costs={'electricity': 1000000},
expansion_limits={'electricity': nts.MinMax(
min=1100, max=float('+inf'))},
)
onshore_wind_turbine = components.Source(
name='Onshore Wind Turbine',
outputs=('electricity',),
sector='Power',
carrier='electricity',
node_type='Renewable',
accumulated_amounts={
'electricity': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'electricity': nts.MinMax(min=0, max=1100)},
flow_costs={'electricity': 60},
flow_emissions={'electricity': 0.02},
flow_gradients={
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'electricity': nts.PositiveNegative(
positive=0, negative=0)},
timeseries={'electricity': nts.MinMax(
min=np.array(periods * [0]),
max=np.array(wind_onshore))},
expandable={'electricity': expansion_problem},
expansion_costs={'electricity': 1750000},
expansion_limits={'electricity': nts.MinMax(
min=1100, max=float('+inf'))},
)
offshore_wind_turbine = components.Source(
name='Offshore Wind Turbine',
outputs=('electricity',),
sector='Power',
carrier='electricity',
node_type='Renewable',
accumulated_amounts={
'electricity': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'electricity': nts.MinMax(min=0, max=150)},
flow_costs={'electricity': 105},
flow_emissions={'electricity': 0.02},
flow_gradients={
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'electricity': nts.PositiveNegative(
positive=0, negative=0)},
timeseries={'electricity': nts.MinMax(
min=np.array(periods * [0]),
max=np.array(wind_offshore))},
expandable={'electricity': expansion_problem},
expansion_costs={'electricity': 3900000},
expansion_limits={'electricity': nts.MinMax(
min=150, max=float('+inf'))},
)
# ---------------- Transformer -----------------------
hard_coal_chp = components.Transformer(
name='Hard Coal CHP',
inputs=('Hard_Coal',),
outputs=('electricity', 'hot_water',),
conversions={('Hard_Coal', 'electricity'): 0.4,
('Hard_Coal', 'hot_water'): 0.4},
sector='Coupled',
carrier='coupled',
node_type='transformer',
flow_rates={
'Hard_Coal': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=0, max=300),
'hot_water': nts.MinMax(min=0, max=300)},
flow_costs={'Hard_Coal': 0, 'electricity': 80, 'hot_water': 6},
flow_emissions={'Hard_Coal': 0, 'electricity': 0.8, 'hot_water': 0.06},
flow_gradients={
'Hard_Coal': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'hot_water': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'Hard_Coal': nts.PositiveNegative(positive=0, negative=0),
'electricity': nts.PositiveNegative(positive=0, negative=0),
'hot_water': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'Hard_Coal': False,
'electricity': expansion_problem, 'hot_water': expansion_problem},
expansion_costs={'Hard_Coal': 0,
'electricity': 1750000, 'hot_water': 131250},
expansion_limits={
'Hard_Coal': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=300, max=float('+inf')),
'hot_water': nts.MinMax(min=300, max=float('+inf'))},
)
hard_coal_power_plant = components.Transformer(
name='Hard Coal PP',
inputs=('Hard_Coal',),
outputs=('electricity',),
conversions={('Hard_Coal', 'electricity'): 0.43},
sector='Power',
carrier='electricity',
node_type='transformer',
flow_rates={
'Hard_Coal': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=0, max=500), },
flow_costs={'Hard_Coal': 0, 'electricity': 80},
flow_emissions={'Hard_Coal': 0, 'electricity': 0.8},
flow_gradients={
'Hard_Coal': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'Hard_Coal': nts.PositiveNegative(positive=0, negative=0),
'electricity': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'Hard_Coal': False, 'electricity': expansion_problem},
expansion_costs={'Hard_Coal': 0, 'electricity': 1650000},
expansion_limits={
'Hard_Coal': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=500, max=float('+inf'))},
)
combined_cycle_power_plant = components.Transformer(
name='Combined Cycle PP',
inputs=('fuel',),
outputs=('electricity',),
conversions={('fuel', 'electricity'): 0.6},
sector='Power',
carrier='electricity',
node_type='transformer',
flow_rates={
'fuel': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=0, max=600)},
flow_costs={'fuel': 0, 'electricity': 90},
flow_emissions={'fuel': 0, 'electricity': 0.35},
flow_gradients={
'fuel': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'fuel': nts.PositiveNegative(positive=0, negative=0),
'electricity': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'fuel': False, 'electricity': expansion_problem},
expansion_costs={'fuel': 0, 'electricity': 950000},
expansion_limits={
'fuel': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=600, max=float('+inf'))},
)
lignite_power_plant = components.Transformer(
name='Lignite Power Plant',
inputs=('lignite',),
outputs=('electricity',),
conversions={('lignite', 'electricity'): 0.4},
sector='Power',
carrier='electricity',
node_type='transformer',
flow_rates={
'lignite': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=0, max=500)},
flow_costs={'lignite': 0, 'electricity': 65},
flow_emissions={'lignite': 0, 'electricity': 1},
flow_gradients={
'lignite': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'lignite': nts.PositiveNegative(positive=0, negative=0),
'electricity': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'lignite': False, 'electricity': expansion_problem},
expansion_costs={'lignite': 0, 'electricity': 1900000},
expansion_limits={
'lignite': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=500, max=float('+inf'))},
)
biogas_chp = components.Transformer(
name='Biogas CHP',
inputs=('biogas',),
outputs=('electricity', 'hot_water',),
conversions={('biogas', 'electricity'): 0.4,
('biogas', 'hot_water'): 0.5},
sector='Coupled',
carrier='coupled',
node_type='transformer',
flow_rates={
'biogas': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=0, max=200),
'hot_water': nts.MinMax(min=0, max=250)},
flow_costs={'biogas': 0, 'electricity': 150, 'hot_water': 11.25},
flow_emissions={'biogas': 0, 'electricity': 0.25, 'hot_water': 0.01875},
flow_gradients={
'biogas': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'hot_water': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'biogas': nts.PositiveNegative(positive=0, negative=0),
'electricity': nts.PositiveNegative(positive=0, negative=0),
'hot_water': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'biogas': False,
'electricity': expansion_problem, 'hot_water': expansion_problem},
expansion_costs={'biogas': 0,
'electricity': 3500000, 'hot_water': 262500},
expansion_limits={
'biogas': nts.MinMax(min=0, max=float('+inf')),
'electricity': nts.MinMax(min=200, max=float('+inf')),
'hot_water': nts.MinMax(min=250, max=float('+inf'))},
)
heat_plant = components.Transformer(
name='Heat Plant',
inputs=('fuel',),
outputs=('hot_water',),
conversions={('fuel', 'hot_water'): 0.9},
sector='Power',
carrier='hot_water',
node_type='transformer',
flow_rates={
'fuel': nts.MinMax(min=0, max=float('+inf')),
'hot_water': nts.MinMax(min=0, max=450)},
flow_costs={'fuel': 0, 'hot_water': 35},
flow_emissions={'fuel': 0, 'hot_water': 0.23},
flow_gradients={
'fuel': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'hot_water': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'fuel': nts.PositiveNegative(positive=0, negative=0),
'hot_water': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'fuel': False, 'hot_water': expansion_problem},
expansion_costs={'fuel': 0, 'hot_water': 390000},
expansion_limits={
'fuel': nts.MinMax(min=0, max=float('+inf')),
'hot_water': nts.MinMax(min=450, max=float('+inf'))},
)
power_to_heat = components.Transformer(
name='Power To Heat',
inputs=('electricity',),
outputs=('hot_water',),
conversions={('electricity', 'hot_water'): 0.99},
sector='Coupled',
carrier='coupled',
node_type='transformer',
flow_rates={
'electricity': nts.MinMax(min=0, max=float('+inf')),
'hot_water': nts.MinMax(min=0, max=100)},
flow_costs={'electricity': 0, 'hot_water': 20},
flow_emissions={'electricity': 0, 'hot_water': 0.0007},
flow_gradients={
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf')),
'hot_water': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={
'electricity': nts.PositiveNegative(positive=0, negative=0),
'hot_water': nts.PositiveNegative(positive=0, negative=0)},
timeseries=None,
expandable={'electricity': False, 'hot_water': expansion_problem},
expansion_costs={'electricity': 0, 'hot_water': 100000},
expansion_limits={
'electricity': nts.MinMax(min=0, max=float('+inf')),
'hot_water': nts.MinMax(min=100, max=float('+inf'))},
)
# ---------------- Storages -----------------------
storage = components.Storage(
name='Battery',
input='electricity',
output='electricity',
capacity=100,
initial_soc=0,
sector='Power',
carrier='electricity',
node_type='storage',
idle_changes=nts.PositiveNegative(positive=0, negative=0.5),
flow_rates={'electricity': nts.MinMax(min=0, max=33)},
flow_efficiencies={
'electricity': nts.InOut(inflow=0.95, outflow=0.95)},
flow_costs={'electricity': 400},
flow_emissions={'electricity': 0.06},
flow_gradients={
'electricity': nts.PositiveNegative(
positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'electricity': nts.PositiveNegative(
positive=0, negative=0)},
timeseries=None,
expandable={'capacity': expansion_problem, 'electricity': expansion_problem},
fixed_expansion_ratios={'electricity': expansion_problem},
expansion_costs={'capacity': 1630000, 'electricity': 0},
expansion_limits={
'capacity': nts.MinMax(min=100, max=float('+inf')),
'electricity': nts.MinMax(min=33, max=float('+inf'))},
)
heat_storage = components.Storage(
name='Heat Storage',
input='hot_water',
output='hot_water',
capacity=50,
initial_soc=0,
sector='Heat',
carrier='hot_water',
node_type='storage',
idle_changes=nts.PositiveNegative(positive=0, negative=0.25),
flow_rates={'hot_water': nts.MinMax(min=0, max=10)},
flow_efficiencies={
'hot_water': nts.InOut(inflow=0.95, outflow=0.95)},
flow_costs={'hot_water': 20},
flow_emissions={'hot_water': 0},
flow_gradients={
'hot_water': nts.PositiveNegative(
positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'hot_water': nts.PositiveNegative(
positive=0, negative=0)},
timeseries=None,
expandable={'capacity': expansion_problem, 'hot_water': expansion_problem},
fixed_expansion_ratios={'hot_water': expansion_problem},
expansion_costs={'capacity': 4500, 'hot_water': 0},
expansion_limits={
'capacity': nts.MinMax(min=50, max=float('+inf')),
'hot_water': nts.MinMax(min=10, max=float('+inf'))},
)
# ---------------- Sinks -----------------------
el_demand = components.Sink(
name='El Demand',
inputs=('electricity',),
sector='Power',
carrier='electricity',
node_type='demand',
accumulated_amounts={
'electricity': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'electricity': nts.MinMax(min=0, max=max_el)},
flow_costs={'electricity': 0},
flow_emissions={'electricity': 0},
flow_gradients={
'electricity': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'electricity': nts.PositiveNegative(
positive=0, negative=0)},
timeseries={'electricity': nts.MinMax(
min=np.array(el_demand),
max=np.array(el_demand))},
expandable={'electricity': False},
expansion_costs={'electricity': 0},
expansion_limits={'electricity': nts.MinMax(
min=0, max=float('+inf'))},
)
heat_demand = components.Sink(
name='Heat Demand',
inputs=('hot_water',),
sector='Heat',
carrier='hot_water',
node_type='demand',
accumulated_amounts={
'hot_water': nts.MinMax(min=0, max=float('+inf'))},
flow_rates={'hot_water': nts.MinMax(min=0, max=max_th)},
flow_costs={'hot_water': 0},
flow_emissions={'hot_water': 0},
flow_gradients={
'hot_water': nts.PositiveNegative(positive=float('+inf'), negative=float('+inf'))},
gradient_costs={'hot_water': nts.PositiveNegative(
positive=0, negative=0)},
timeseries={'hot_water': nts.MinMax(
min=np.array(th_demand),
max=np.array(th_demand))},
expandable={'hot_water': False},
expansion_costs={'hot_water': 0},
expansion_limits={'hot_water': nts.MinMax(
min=0, max=float('+inf'))},
)
# ---------------- Busses -----------------------
fuel_supply_line = components.Bus(
name='Gas Line',
inputs=('Gas Station.fuel',),
outputs=('Combined Cycle PP.fuel', 'Heat Plant.fuel'),
sector='Coupled',
carrier='Gas',
node_type='bus',
)
biogas_supply_line = components.Bus(
name='Biogas Line',
inputs=('Biogas Supply.biogas',),
outputs=('Biogas CHP.biogas',),
sector='Coupled',
carrier='Biogas',
node_type='bus',
)
hard_coal_supply_line = components.Bus(
name='Hard Coal Supply Line',
inputs=('Hard Coal Supply.Hard_Coal',),
outputs=('Hard Coal PP.Hard_Coal', 'Hard Coal CHP.Hard_Coal',),
sector='Coupled',
carrier='Hard_Coal',
node_type='bus',
)
lignite_supply_line = components.Bus(
name='Lignite Supply Line',
inputs=('Lignite Supply.lignite',),
outputs=('Lignite Power Plant.lignite',),
sector='Power',
carrier='Lignite',
node_type='bus',
)
electricity_line = components.Bus(
name='Powerline',
inputs=('Combined Cycle PP.electricity', 'Battery.electricity',
'Lignite Power Plant.electricity', 'Hard Coal PP.electricity',
'Hard Coal CHP.electricity', 'Solar Panel.electricity',
'Offshore Wind Turbine.electricity', 'Biogas CHP.electricity',
'Onshore Wind Turbine.electricity',
),
outputs=('El Demand.electricity', 'Battery.electricity',
'Power To Heat.electricity'),
sector='Power',
carrier='electricity',
node_type='bus',
)
heat_line = components.Bus(
name='Heatline',
inputs=('Heat Plant.hot_water', 'Hard Coal CHP.hot_water', 'Biogas CHP.hot_water',
'Power To Heat.hot_water', 'Heat Storage.hot_water'),
outputs=('Heat Demand.hot_water', 'Heat Storage.hot_water'),
sector='Heat',
carrier='hot_water',
node_type='bus',
)
# Creating the actual energy system:
explicit_es = energy_system.AbstractEnergySystem(
uid=f'Component_{use_case}_es', # adjusted
busses=(fuel_supply_line, electricity_line, hard_coal_supply_line,
lignite_supply_line, biogas_supply_line, heat_line,),
sinks=(el_demand, heat_demand),
sources=(fuel_supply, solar_panel, onshore_wind_turbine, hard_coal_supply,
lignite_supply, offshore_wind_turbine, biogas_supply,),
transformers=(combined_cycle_power_plant, hard_coal_power_plant, lignite_power_plant,
biogas_chp, heat_plant, power_to_heat, hard_coal_chp),
storages=(storage, heat_storage),
timeframe=timeframe,
global_constraints=global_constraints,
)
return explicit_es