Result Data Representation
The developed method for comparing energy supply system models recommends a specific result data representation based on a directed graph.
Following script shows how to use Tessif’s
post processing utility to compile
the result data for a singular component. It is intended to serve as copy-paste
template as well as basis for further use.
It is the very same script which was used to generate the generic graph visualization and tabular result data representation in the phd’s subsection:
Theory -> Graph Theory Tools -> Result Data Representation
The compilation utility can be used via tessif as
tessif.transform.es2mapping.compile_result_data_representation().
Examplary Use
import importlib
import matplotlib.pyplot as plt
from pathlib import Path
import tessif.simulate as optimize
from tessif.model.energy_system import AbstractEnergySystem as AES
from tessif import parse
from tessif.frused import configurations
from tessif.frused.paths import doc_dir
from tessif.transform.es2mapping import compile_result_data_representation
import tessif.visualize.nxgrph as nxv
# silence spellings mismatch warnings
configurations.spellings_logging_level = 'debug'
# construct the absolute path of the system model data
p = Path(doc_dir) / "source" / "getting_started" / "examples"
p = p / "application" / "phd" / "rdr" / "esm"
FOLDER = p.resolve()
# create the system model
es = AES.from_external(path=FOLDER, parser=parse.flat_config_folder)
# create the visual representation
drawing_data = nxv.draw_graph(
es.to_nxgrph(),
node_color={
'CBES': '#666666',
'CBE Bus': '#666666',
'CHP': '#666666',
'Heatline': '#b30000',
'Heat Demand': '#b30000',
'Power Demand': '#ffe34d',
'Powerline': '#ffe34d',
},
node_size={
'powerline': 5000,
'district heating pipeline': 5000
},
)
# plt.show()
software = "fine"
transformation_module = importlib.import_module(
'.'.join(['tessif.transform.es2es', software]))
# 7. Transform the tessif system model into a fine system model:
software_es = transformation_module.transform(es)
# 8. Optimize the fine system model using fine's capabilities:
optimized_es = getattr(optimize, "_".join([software, "from_es"]))(software_es)
rdr = compile_result_data_representation(optimized_es, software, 'CHP')
print(rdr)
Examplary result
The above code snippet prints following result:
Symbol Value
Label
installed capacity $P_{cap}$ {'Powerline': 4.0, 'Heatline': 5.0}
original capacity $P_{origcap}$ {'Powerline': 0.0, 'Heatline': 0.0}
characteristic value $cv$ {'Powerline': 1.0, 'Heatline': 1.0}
energy carrier - cbe
energy sector - coupled
region - example region
component - transformer
node_type - Combined Heat and Power Plant
latitude - 53.46025
longitude - 9.969309
load $P(t)$ {'CBE Bus': [-10.0, -10.0, -10.0], 'Heatline':...
net energy flow $\sum_t P(t)$ {'Powerline': 12.0, 'Heatline': 15.0}
specific costs $c_{flow}$ {'Powerline': 2.0, 'Heatline': 1.0}
specific emissions $e_{flow}$ {'Powerline': 0.0, 'Heatline': 0.0}
Compilation Utility Source Code
The utility can be accessed via tessif as demonstrated above using
tessif.transform.es2mapping.compile_result_data_representation().
import pandas as pd
import importlib
def compile_result_data_representation(optimized_es, software, node):
"""
Convenience wrapper to compile result data representation.
Explicitly reproduces the result data representation table as stated in the
lead author's phd thesis in
'Theory' -> 'Graph Theory Tools' -> 'Result Data Representation'
Parameters
----------
optimized_es: software_specific_optimized_energy_system
An optimized energy system containing its results as in tessif.simulate
software: str
String naming the
:attr:`~tessif.frused.defaults.registered_models` representing tessif's
:ref:`supported energy supply system simulation models<SupportedModels>`
node: str
String representing the node's
:class:`uids <tessif.frused.namedtuples.Uid>` of which the result data
representation is to be compiled.
"""
requested_model_result_parsing_module = importlib.import_module(
'.'.join(['tessif.transform.es2mapping', software]))
resultier = requested_model_result_parsing_module.AllResultier(
optimized_es)
# compile first three straight forward result datas:
result_data = [
('installed capacity', '$P_{cap}$',
_compile_node_from_res(resultier, 'node_installed_capacity', node)),
('original capacity', '$P_{origcap}$',
_compile_node_from_res(resultier, 'node_original_capacity', node)),
('characteristic value', '$cv$',
_compile_node_from_res(resultier, 'node_characteristic_value', node)),
]
# check if SOC(t) is applicable:
if node in resultier.node_soc:
result_data.append(
('current SOC', '$SOC(t)$', resultier.node_soc[node])
)
# continue compiling the rest of the node data:
result_data.extend(
[
('energy carrier', '-', resultier.uid_nodes[node].carrier),
('energy sector', '-', resultier.uid_nodes[node].sector),
('region', '-', resultier.uid_nodes[node].region),
('component', '-', resultier.uid_nodes[node].component),
('node_type', '-', resultier.uid_nodes[node].node_type),
('latitude', '-', resultier.uid_nodes[node].latitude),
('longitude', '-', resultier.uid_nodes[node].longitude),
],
)
# compile edge data
node_outflows = resultier.outbounds[node]
net_energy_flows = dict()
specific_costs = dict()
specific_emissions = dict()
for outflow in node_outflows:
net_energy_flows[outflow] = resultier.edge_net_energy_flow[(
node, outflow)]
specific_costs[outflow] = resultier.edge_specific_flow_costs[(
node, outflow)]
specific_emissions[outflow] = resultier.edge_specific_emissions[(
node, outflow)]
result_data.extend(
[
('load', '$P(t)$', _compile_node_from_res(
resultier, 'node_load', node)),
('net energy flow', '$\\sum_t P(t)$', net_energy_flows),
('specific costs', '$c_{flow}$', specific_costs),
('specific emissions', '$e_{flow}$', specific_emissions),
],
)
# print(result_data)
# create a Pandas DataFrame to increase readability and math thesis layout:
result_df = pd.DataFrame(result_data, columns=['Label', 'Symbol', 'Value'])
result_df = result_df.set_index('Label')
return result_df
def _compile_node_from_res(resultier, attribute, node):
result = getattr(resultier, attribute)[node]
if attribute == "node_load":
new_result = dict()
for col in result.columns:
new_result[col] = result[col].values.tolist()
return new_result
if isinstance(result, pd.DataFrame):
return dict(result)
else:
return result
Raw Energy System Data
Following are the raw data files with which the energy system above was created.
Original Data – Configuration File Busses
[cbe_transport]
"name" = 'CBE Bus'
"inputs" = ('CBES.CBE',)
"outputs" =('CHP.CBE',)
[power_line]
"name" = 'Powerline'
"inputs" = ('CHP.power', )
"outputs" = ('Power Demand.power',)
[heat_line]
"name" = 'Heatline'
"inputs" = ('CHP.heat', )
"outputs" = ('Heat Demand.heat',)
Original Data – Configuration File Sources
[chemically_bound_energy_source]
"name" = "CBES"
"outputs" = ("CBE", )
Original Data – Configuration File Sinks
[power_demand]
'name' = 'Power Demand'
'inputs' = ('power',)
'flow_rates' = {'power': (4, 4)}
[heat_demand]
'name' = 'Heat Demand'
'inputs' = ('heat',)
'flow_rates' = {'heat': (5, 5)}
Original Data – Configuration File Transformers
[combined_heat_and_power_plant]
"name" = 'CHP'
"inputs" = ('CBE',)
"carrier" = 'cbe'
"sector" = 'coupled'
"region" ='example region'
"node_type" ='Combined Heat and Power Plant'
"component" = 'transformer'
"latitude" = 53.46025
"longitude" =9.969309
"outputs" = ('power', 'heat')
"conversions"= {
('CBE', 'power'): 0.4,
('CBE', 'heat'): 0.5}
"flow_costs" = {'power': 2, 'heat': 1, 'CBE': 0}
Original Data – Configuration File Timeframe
# for specifying timeframes see https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.date_range.html
[primary]
start = '01-01-2015'
periods = 3
freq = 'H'
Original Data – Configuration File Global Constraints
[primary]
name = 'default'
# emissions = '+inf'
emissions = 10000
material = '+inf'