Code Base
Following section display the code snippets that were used to create the TransC/E results and diagrams.
System-Model-Scenario-Combination Creation Code
Following code snippet shows how to create the TransC/E combinations
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
def create_losslc_es(periods=24,):
"""
Create the TransCnE system model scenarios combinations.
Parameters
----------
periods : int, default=24
Number of time steps of the evaluated timeframe (one time step is one
hour)
Note
----
Changes compared to `Hanke Project Thesis
<https://tore.tuhh.de/handle/11420/11759>`_:
1. Rename ``"[High/Mid/Low] Voltage Powerline"`` to ``"[High/Mid/Low]
Voltage Grid"``
2. Rename ``"[High/Low] Voltage Transformator"`` to ``"[High/Low]
Voltage Transfer Grid"``
Return
------
es: :class:`tessif.model.energy_system.AbstractEnergySystem`
Tessif energy system.
"""
# 2. Create a simulation time frame as a :class:`pandas.DatetimeIndex`:
timeframe = pd.date_range('10/13/2030', periods=periods, freq='H')
# 3. Parse csv files with the demand and renewables load data:
d = os.path.join(example_dir, 'data', 'tsf', 'load_profiles')
# solar:
pv = pd.read_csv(os.path.join(d, 'Renewable_Energy.csv'),
index_col=0, sep=';')
pv = pv['pv_load'].values.flatten()[0:periods]
max_pv = np.max(pv)
# wind onshore:
w_on = pd.read_csv(os.path.join(
d, 'Renewable_Energy.csv'), index_col=0, sep=';')
w_on = w_on['won_load'].values.flatten()[0:periods]
max_w_on = np.max(w_on)
# wind offshore:
w_off = pd.read_csv(os.path.join(
d, 'Renewable_Energy.csv'), index_col=0, sep=';')
w_off = w_off['woff_load'].values.flatten()[0:periods]
max_w_off = np.max(w_off)
# solar thermal:
s_t = pd.read_csv(os.path.join(
d, 'Renewable_Energy.csv'), index_col=0, sep=';')
s_t = s_t['st_load'].values.flatten()[0:periods]
max_s_t = np.max(s_t)
# household demand
h_d = pd.read_csv(os.path.join(d, 'Loads.csv'), index_col=0, sep=';')
h_d = h_d['household_demand'].values.flatten()[0:periods]
max_h_d = np.max(h_d)
# industrial demand
i_d = pd.read_csv(os.path.join(d, 'Loads.csv'), index_col=0, sep=';')
i_d = i_d['industrial_demand'].values.flatten()[0:periods]
max_i_d = np.max(i_d)
# commercial demand
c_d = pd.read_csv(os.path.join(d, 'Loads.csv'), index_col=0, sep=';')
c_d = c_d['commercial_demand'].values.flatten()[0:periods]
max_c_d = np.max(c_d)
# district heating demand
dh_d = pd.read_csv(os.path.join(d, 'Loads.csv'), index_col=0, sep=';')
dh_d = dh_d['heat_demand'].values.flatten()[0:periods]
max_dh_d = np.max(dh_d)
# car charging demand
cc_d = pd.read_csv(os.path.join(d, 'Car_Charging.csv'),
index_col=0, sep=';')
cc_d = cc_d['cc_demand'].values.flatten()[0:periods]
max_cc_d = np.max(cc_d)
# 4. Create the individual energy system components:
global_constraints = {
'name': 'default',
'emissions': float('+inf'),
}
# -------------Low Voltage and heat ------------------
solar_panel = components.Source(
name='Solar Panel',
outputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='Electricity',
node_type='Renewable',
flow_rates={'electricity': nts.MinMax(min=0, max=max_pv)},
flow_costs={'electricity': 60.85},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=pv, max=pv)},
)
biogas_supply = components.Source(
name='Biogas plant',
outputs=('fuel',),
# Minimum number of arguments required
sector='Coupled',
carrier='Gas',
node_type='source',
flow_rates={'fuel': nts.MinMax(min=0, max=25987.87879)},
flow_costs={'fuel': 0},
flow_emissions={'fuel': 0},
)
bhkw_generator = components.Transformer(
name='BHKW',
inputs=('fuel',),
outputs=('electricity', 'heat'),
conversions={('fuel', 'electricity'): 0.33, ('fuel', 'heat'): 0.52},
# Minimum number of arguments required
sector='Coupled',
carrier='electricity',
node_type='transformer',
flow_rates={
'fuel': nts.MinMax(min=0, max=25987.87879),
'electricity': nts.MinMax(min=0, max=8576),
'heat': nts.MinMax(min=0, max=13513.69697)},
flow_costs={'fuel': 0, 'electricity': 124.4, 'heat': 31.1},
flow_emissions={'fuel': 0, 'electricity': 0.1573, 'heat': 0.0732},
)
household_demand = components.Sink(
name='Household Demand',
inputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='demand',
flow_rates={'electricity': nts.MinMax(min=0, max=max_h_d)},
flow_costs={'electricity': 0},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=h_d, max=h_d)},
)
commercial_demand = components.Sink(
name='Commercial Demand',
inputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='demand',
flow_rates={'electricity': nts.MinMax(min=0, max=max_c_d)},
flow_costs={'electricity': 0},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=c_d, max=c_d)},
)
heat_demand = components.Sink(
name='District Heating Demand',
inputs=('heat',),
# Minimum number of arguments required
sector='Heat',
carrier='hot Water',
node_type='demand',
flow_rates={'heat': nts.MinMax(min=0, max=max_dh_d)},
flow_costs={'heat': 0},
flow_emissions={'heat': 0},
timeseries={'heat': nts.MinMax(min=dh_d, max=dh_d)},
)
gas_supply_line = components.Bus(
name='Gaspipeline',
inputs=('Gas Station.fuel',),
outputs=('GuD.fuel',),
# Minimum number of arguments required
sector='Power',
carrier='gas',
node_type='bus',
)
biogas_supply_line = components.Bus(
name='Biogas',
inputs=('Biogas plant.fuel',),
outputs=('BHKW.fuel',),
# Minimum number of arguments required
sector='Coupled',
carrier='gas',
node_type='bus',
)
low_electricity_line = components.Bus(
name='Low Voltage Powerline',
inputs=(
'BHKW.electricity',
'Battery.electricity',
'Solar Panel.electricity',
),
outputs=(
'Household Demand.electricity',
'Commercial Demand.electricity',
'Battery.electricity',
),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='bus',
)
heat_line = components.Bus(
name='District Heating',
inputs=(
'BHKW.heat',
'Solar Thermal.heat',
'Heat Storage.heat',
'Power to Heat.heat',
'HKW.heat',
),
outputs=(
'District Heating Demand.heat',
'Heat Storage.heat',
),
# Minimum number of arguments required
sector='Heat',
carrier='hot Water',
node_type='bus',
)
# ----- -------Medium Voltage and Heat ------------------
onshore_wind_power = components.Source(
name='Onshore Wind Power',
outputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='Electricity',
node_type='Renewable',
flow_rates={'electricity': nts.MinMax(min=0, max=max_w_on)},
flow_costs={'electricity': 61.1},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=w_on, max=w_on)},
)
solar_thermal = components.Source(
name='Solar Thermal',
outputs=('heat',),
# Minimum number of arguments required
sector='Heat',
carrier='Hot Water',
node_type='Renewable',
flow_rates={'heat': nts.MinMax(min=0, max=max_s_t)},
flow_costs={'heat': 73},
flow_emissions={'heat': 0},
timeseries={'heat': nts.MinMax(min=s_t, max=s_t)},
)
industrial_demand = components.Sink(
name='Industrial Demand',
inputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='demand',
flow_rates={'electricity': nts.MinMax(min=0, max=max_i_d)},
flow_costs={'electricity': 0},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=i_d, max=i_d)},
)
car_charging_station_demand = components.Sink(
name='Car charging Station',
inputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='demand',
flow_rates={'electricity': nts.MinMax(min=0, max=max_cc_d)},
flow_costs={'electricity': 0},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=cc_d, max=cc_d)},
)
power_to_heat = components.Transformer(
name='Power to Heat',
inputs=('electricity',),
outputs=('heat',),
conversions={('electricity', 'heat'): 1.00},
# Minimum number of arguments required
carrier='Hot Water',
node_type='transformer',
flow_rates={
'electricity': nts.MinMax(min=0, max=50000),
'heat': nts.MinMax(min=0, max=50000),
},
flow_costs={'electricity': 0, 'heat': 0},
flow_emissions={'electricity': 0, 'heat': 0},
)
medium_electricity_line = components.Bus(
name='Medium Voltage Grid',
inputs=('Onshore Wind Power.electricity',),
outputs=(
'Car charging Station.electricity',
'Industrial Demand.electricity',
'Power to Heat.electricity',
),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='bus',
)
low_medium_transformator = components.Connector(
name='Low Voltage Transfer Grid',
interfaces=(
'Medium Voltage Grid',
'Low Voltage Powerline'),
conversions={
('Medium Voltage Grid', 'Low Voltage Powerline'): 1,
('Low Voltage Powerline', 'Medium Voltage Grid'): 1,
},
node_type='connector',
)
# ----------------- High Voltage -------------------------
offshore_wind_power = components.Source(
name='Offshore Wind Power',
outputs=('electricity',),
# Minimum number of arguments required
sector='Power',
carrier='Electricity',
node_type='Renewable',
flow_rates={'electricity': nts.MinMax(min=0, max=max_w_off)},
flow_costs={'electricity': 106.4},
flow_emissions={'electricity': 0},
timeseries={'electricity': nts.MinMax(min=w_off, max=w_off)},
)
coal_supply = components.Source(
name='Coal Supply',
outputs=('fuel',),
# Minimum number of arguments required
sector='Coupled',
carrier='Coal',
node_type='source',
flow_rates={'fuel': nts.MinMax(min=0, max=102123.3)},
flow_costs={'fuel': 0},
flow_emissions={'fuel': 0},
)
gas_supply = components.Source(
name='Gas Station',
outputs=('fuel',),
# Minimum number of arguments required
sector='Power',
carrier='Gas',
node_type='source',
flow_rates={'fuel': nts.MinMax(min=0, max=float('+inf'))},
flow_costs={'fuel': 0},
flow_emissions={'fuel': 0},
)
hkw_generator = components.Transformer(
name='HKW',
inputs=('fuel',),
outputs=('electricity', 'heat'),
conversions={('fuel', 'electricity'): 0.24, ('fuel', 'heat'): 0.6},
# Minimum number of arguments required
sector='Coupled',
carrier='electricity',
node_type='transformer',
flow_rates={
'fuel': nts.MinMax(min=0, max=102123.3),
'electricity': nts.MinMax(min=0, max=24509.6),
'heat': nts.MinMax(min=0, max=61273.96)},
flow_costs={'fuel': 0, 'electricity': 80.65, 'heat': 20.1625},
flow_emissions={'fuel': 0, 'electricity': 0.5136, 'heat': 0.293},
)
hkw_generator_2 = components.Transformer(
name='HKW2',
inputs=('fuel',),
outputs=('electricity',),
conversions={('fuel', 'electricity'): 0.43},
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='connector',
flow_rates={
'fuel': nts.MinMax(min=0, max=102123.3),
'electricity': nts.MinMax(min=0, max=43913)},
flow_costs={'fuel': 0, 'electricity': 80.65},
flow_emissions={'fuel': 0, 'electricity': 0.5136},
)
gud_generator = components.Transformer(
name='GuD',
inputs=('fuel',),
outputs=('electricity',),
conversions={('fuel', 'electricity'): 0.59},
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='transformer',
flow_rates={
'fuel': nts.MinMax(min=0, max=45325.42373),
'electricity': nts.MinMax(min=0, max=26742)},
flow_costs={'fuel': 0, 'electricity': 88.7},
flow_emissions={'fuel': 0, 'electricity': 0.3366},
)
coal_supply_line = components.Bus(
name='Coal Supply Line',
inputs=('Coal Supply.fuel',),
outputs=('HKW.fuel', 'HKW2.fuel'),
# Minimum number of arguments required
sector='Coupled',
carrier='Coal',
node_type='bus',
)
high_electricity_line = components.Bus(
name='High Voltage Grid',
inputs=(
'Offshore Wind Power.electricity',
'GuD.electricity',
'HKW.electricity',
'HKW2.electricity',
),
outputs=('Power Sink.electricity',),
# Minimum number of arguments required
sector='Power',
carrier='electricity',
node_type='bus',
)
high_medium_transformator = components.Connector(
name='High Voltage Transfer Grid',
interfaces=(
'Medium Voltage Grid',
'High Voltage Grid',
),
conversions={
('Medium Voltage Grid', 'High Voltage Grid'): 1,
('High Voltage Grid', 'Medium Voltage Grid'): 1,
},
node_type='connector',
)
# 4. Create the actual energy system:
es = energy_system.AbstractEnergySystem(
uid="LossLC",
busses=(
gas_supply_line,
low_electricity_line,
heat_line,
medium_electricity_line,
high_electricity_line,
coal_supply_line,
biogas_supply_line,
),
sinks=(
household_demand,
commercial_demand,
heat_demand,
industrial_demand,
car_charging_station_demand,
),
sources=(
solar_panel,
gas_supply,
onshore_wind_power,
offshore_wind_power,
coal_supply,
solar_thermal,
biogas_supply,
),
transformers=(
bhkw_generator,
power_to_heat,
gud_generator,
hkw_generator,
hkw_generator_2,
),
connectors=(
low_medium_transformator,
high_medium_transformator,
),
timeframe=timeframe,
global_constraints=global_constraints,
)
return es
Generic Graph
The LossLC Generic Graph image was crated using following code
snippet:
import matplotlib.pyplot as plt
import tessif.visualize.dcgrph as dcv
import tessif.examples.data.tsf.py_hard as tsf_py
tsf_es = tsf_py.create_losslc_es()
# grph = tsf_es.to_nxgrph()
app = dcv.draw_generic_graph(
energy_system=tsf_es,
color_group={
'Coal Supply': '#666666',
'Coal Supply Line': '#666666',
'HKW': '#666666',
'HKW2': '#666666',
'Solar Thermal': '#b30000',
'Heat Storage': '#cc0033',
'District Heating': 'Red',
'District Heating Demand': 'Red',
'Power to Heat': '#b30000',
'Biogas plant': '#006600',
'Biogas': '#006600',
'BHKW': '#006600',
'Onshore Wind Power': '#99ccff',
'Offshore Wind Power': '#00ccff',
'Gas Station': '#336666',
'Gaspipeline': '#336666',
'GuD': '#336666',
'Solar Panel': '#ffe34d',
'Commercial Demand': '#ffe34d',
'Household Demand': '#ffe34d',
'Industrial Demand': '#ffe34d',
'Car charging Station': '#669999',
'Low Voltage Grid': '#ffcc00',
'Medium Voltage Grid': '#ffcc00',
'High Voltage Grid': '#ffcc00',
'High Voltage Transfer Grid': 'yellow',
'Low Voltage Transfer Grid': 'yellow',
},
node_size={
'High Voltage Transfer Grid': 150,
'Low Voltage Transfer Grid': 150,
'District Heating': 150
},
title='Lossless Power Grid Example Energy System Graph',
)
app.run_server(debug=False)
Optimization Results
Shown below, is the code to generate the LossLC results. Use the PERIODS
constant to adjust the simulated time span. Results displayed were created
using PERIODS = 24.
Optimize and Post Process via Tessif
Following script uses the LossLC creation skript above to generate and tessif internally post-process the optimization results, ready for further analysis.
import pandas as pd
import json
import importlib
import os
from pathlib import Path
from tessif.analyze import ComparativeResultier
from tessif.frused.paths import doc_dir
import tessif.examples.data.tsf.py_hard as tsf_examples
import tessif.simulate as optimize
from tessif.transform.es2mapping import compile_result_data_representation
# Change this to 8760 and "exp_results" for the full results.
# (Takes about 30min - 1h)
PERIODS = 24
FOLDER = "results"
FOLDER = "losslc_results"
PARENT = os.path.join(
doc_dir,
"source",
"getting_started",
"examples",
"application",
"phd",
"field_study",
"LossLC",
)
# create dispatch problem aka LossLC combination
tessif_LossLC = tsf_examples.create_losslc_es(periods=PERIODS)
# define the softwares to be used
SOFTWARES = ['cllp', 'fine', 'omf', 'ppsa', ]
# use this in case you are just testing out the water
# SOFTWARES = ['cllp', ]
# dynamically access the tessif transform utilities based on requested
# softwares above. Store them in a dictionairy for
# ease of access.
transformers = {}
for software in SOFTWARES:
transformers[software] = importlib.import_module(
'.'.join(['tessif.transform.es2es', software]))
# Do the tessif -> software transformations and store them in a dictionairy for
# ease of access
transformed_LossLC_combinations = {}
for software in SOFTWARES:
transformed_LossLC_combinations[software] = transformers[software].transform(
tessif_LossLC)
# Perform the software specific optimizations
optimized_LossLC_combinations = {}
for software in SOFTWARES:
optimizer = getattr(optimize, "_".join([software, "from_es"]))
optimized_LossLC_combinations[software] = optimizer(
transformed_LossLC_combinations[software])
# post process the allresultiers:
all_resultiers = {}
for software in SOFTWARES:
post_processor = importlib.import_module(
'.'.join(['tessif.transform.es2mapping', software]))
all_resultiers[software] = post_processor.AllResultier(
optimized_LossLC_combinations[software])
# post process the comparative results using the constructed all-resultiers:
comparatier = ComparativeResultier(all_resultiers)
data_storage_path = os.path.join(PARENT, FOLDER)
# store the all_loads results
for software in SOFTWARES:
result_id = f"{software}_all_loads"
storage_location = os.path.join(data_storage_path, result_id)
result_df = comparatier.all_loads[software]
result_df.to_csv(".".join([storage_location, "csv"]))
# store the all_socs results
result_id = f"all_socs"
storage_location = os.path.join(data_storage_path, result_id)
result_df = comparatier.all_socs
if not result_df.empty:
result_df.to_csv(".".join([storage_location, "csv"]))
# store the rest of the all_* results:
for rtype in [
"all_capacities",
"all_original_capacities",
"all_net_energy_flows",
"all_costs_incurred",
"all_emissions_caused",
]:
result_id = rtype
storage_location = os.path.join(data_storage_path, result_id)
result_df = getattr(comparatier, rtype)
result_df.to_csv(".".join([storage_location, "csv"]))
result_types = ['Load', 'Capacity', 'IntegratedGlobal']
post_processed_data = {}
for software in SOFTWARES:
post_processor = importlib.import_module(
'.'.join(['tessif.transform.es2mapping', software]))
post_processed_data[software] = {}
for result_type in result_types:
post_processed_data[software][result_type] = getattr(
post_processor, "".join([result_type, "Resultier"]))(
optimized_LossLC_combinations[software])
wanted_results = {
'Load': 'node_load',
'Capacity': 'node_installed_capacity',
'IntegratedGlobal': 'global_results',
}
nodes_of_interest = {
'Load': [
'High Voltage Grid',
"Medium Voltage Grid",
"Low Voltage Grid",
'District Heating',
],
'Capacity': [],
'IntegratedGlobal': [],
}
for software in SOFTWARES:
for rtype in result_types:
if nodes_of_interest[rtype]:
for node in nodes_of_interest[rtype]:
result_id = f"{software}_{rtype}_{node}"
storage_location = os.path.join(data_storage_path, result_id)
res = getattr(post_processed_data[software][rtype], wanted_results[rtype])[
node]
if rtype == 'Load':
res = res.sum()
res.name = result_id
res.to_json(
".".join([storage_location, "json"]), orient="split")
else:
result_id = f"{software}_{rtype}"
storage_location = os.path.join(data_storage_path, result_id)
res = getattr(
post_processed_data[software][rtype], wanted_results[rtype])
res = pd.Series(res.values(), index=res.keys())
res.name = result_id
res.to_json(
".".join([storage_location, "json"]), orient="split")
# Use this in case you want to see the result representation of certain nodes
# rdrs = {}
# for software in SOFTWARES:
# rdrs[software] = compile_result_data_representation(
# optimized_es=optimized_LossLC_combinations[software],
# software=software,
# node="Heatline",
# )
# # print(rdrs['fine'])
Aggregate, Compare, and Store Representative Results
Following script takes the stored and post processed results from the optimization process above and turns them into representative csv files shown in the results section.
import pandas as pd
from numpy import int_
import os
from collections import defaultdict
import numbers
from tessif.frused.paths import doc_dir
FOLDER = "results"
# locate the storage directory
cp = os.path.join(
doc_dir, "source", "getting_started", "examples", "application",
"phd", "model_scenario_combinations", "LossLC", FOLDER
)
softwares = ['cllp', 'fine', 'omf', 'ppsa', ]
# use this in case you are just testing out the water
# softwares = ['fine', ]
load_nodes = [
'High Voltage Grid',
"Medium Voltage Grid",
"Low Voltage Grid",
'District Heating',
]
# Result dicts for convenience access
globalesque_results = {}
load_results = {}
for software in softwares:
load_results[software] = {}
for node in load_nodes:
load_result_file = f"{software}_Load_{node}"
storage_path = os.path.join(cp, ".".join([load_result_file, "json"]))
ser = pd.read_json(
storage_path, orient="split", typ="series")
ser.name = load_result_file
load_results[software][node] = ser
globalesque_results[software] = {}
for rtype in ["Capacity", "IntegratedGlobal"]:
result_file = f"{software}_{rtype}"
storage_path = os.path.join(cp, ".".join([result_file, "json"]))
ser = pd.read_json(
storage_path, orient="split", typ="series")
ser.name = result_file
globalesque_results[software][rtype] = ser
# flatten capacity and igr results for better readability:
capacity_results = {}
integrated_global_results = {}
for software in softwares:
capacity_results[software] = globalesque_results[software]["Capacity"]
integrated_global_results[software] = globalesque_results[software]["IntegratedGlobal"]
# aggregate software results into one dataframe for ease of comparison
load_by_node = defaultdict(dict)
for software in softwares:
for node in load_nodes:
load_by_node[node][software] = load_results[software][node]
labels = ["Capacity", "IGR", "Load-High Voltage Grid",
"Load-Medium Voltage Grid", "Load-Low Voltage Grid", "Load-District Heating"]
dimensions = ["MW or MWh", "€ or t_CO2", "MW", "MW", "MW", "MW"]
for pos, dct in enumerate([
capacity_results,
integrated_global_results,
load_by_node["High Voltage Grid"],
load_by_node["Medium Voltage Grid"],
load_by_node["Low Voltage Grid"],
load_by_node["District Heating"],
]):
df = pd.concat(
dct.values(),
keys=dct.keys(),
axis='columns')
# give dataframe a name for higher recognition value
df.index.name = labels[pos] + f" [{dimensions[pos]}]"
# sort dataframe for index
df = df.sort_index()
# change None to "variable" since that is what it means
df = df.fillna("variable")
# cast values into integers, since they are deemed to provide enough
# information
df = df.applymap(
lambda x: int_(x) if isinstance(x, numbers.Number) else x,
# na_action="ignore",
)
# dynamically create the filename using the df.index name
storage_path = os.path.join(cp, ".".join([labels[pos], "csv"]))
# store the result dfs as csv for convenient access
df.to_csv(storage_path)
IGR Bar Plot Code
The Integrated Global Result bar plots from above are created using following code:
import pandas as pd
from pathlib import Path
from tessif.frused.paths import doc_dir
from tessif.visualize import igr
mpl_config = {
"title": "Integrated Global Results Relative to 'Oemof'",
"ylabel": "",
"xlabel": "Result Values",
"rot": 0,
}
for result in ["results", ]:
igr_results_csv_path = (
Path(doc_dir)
/ "source"
/ "getting_started"
/ "examples"
/ "application"
/ "phd"
/ "model_scenario_combinations"
/ "LossLC"
/ result
/ "IGR.csv"
)
result_df = pd.read_csv(igr_results_csv_path, index_col=0)
# make results relative to oemof
result_df = result_df.div(result_df['omf'], axis='index')
# mpl_config["ylim"] = [
# math.floor(10*result_df.min().min())/10,
# math.ceil(10*result_df.max().max())/10,
# ]
handle = igr.plot(
igr_df=result_df,
plt_config=mpl_config,
ptype="bar",
)
for category in ["costs", "non_costs"]:
figure_storage_path = igr_results_csv_path.parents[0] / "_".join(
[category, "IGR.png"])
handle[category].savefig(figure_storage_path)
# handle["costs"].show()
# handle["non_costs"].show()
plexp_config = {
"title": "Integrated Global Results Relative to 'Oemof (omf)'",
"barmode": "group",
"text_auto": True,
}
handle = igr.plot(
igr_df=result_df,
plt_config=plexp_config,
ptype="bar",
draw_util="plexp",
)
handle["costs"].show()
handle["non_costs"].show()
Comutational Ressources
Computational Ressources Estimation Code
The computational ressources bar plots from above are created using following code:
# change spellings_logging_level to debug to declutter output
import tessif.analyze
import tessif.frused.configurations as configurations # nopep8
configurations.spellings_logging_level = 'debug'
import tessif.examples.data.tsf.py_hard as tsf_examples # nopep8
# Import path settings
from tessif.frused.paths import doc_dir # nopep8
import os # nopep8
PERIODS = 24
FOLDER = "results"
# EXPANSION = True
SOFTWARES = ('cllp', 'fine', 'omf', 'ppsa', )
# SOFTWARES = ('cllp',)
HOOK_PYPSA = False
# locate the storage directory
current_path = os.path.join(
doc_dir, "source", "getting_started", "examples", "application",
"phd", "model_scenario_combinations", "LossLC", FOLDER
)
def reparam_ppsa(tessif_es):
reparameterized_es = reparameterize_components(
es=tessif_es,
components={
'Hard Coal CHP': {
'flow_emissions': {'Hard_Coal': 0, 'electricity': 0, 'hot_water': 0},
},
'Hard Coal Supply': {
'flow_emissions': {'Hard_Coal': 0.8 * 0.4 + 0.06 * 0.4},
},
'Biogas CHP': {
'flow_emissions': {'biogas': 0, 'electricity': 0, 'hot_water': 0},
},
'Biogas Supply': {
'flow_emissions': {'biogas': 0.25 * 0.4 + 0.01875 * 0.5},
},
},
)
return reparameterized_es
hook = None
if HOOK_PYPSA:
hook = reparam_ppsa
# Choose the underlying energy system
tsf_es = tsf_examples.create_component_es(periods=PERIODS)
# write it to disk, so the comparatier can read it out
import os # nopep8
from tessif.frused.paths import write_dir # nopep8
output_msg = tsf_es.to_hdf5(
directory=os.path.join(write_dir, 'tsf'),
filename='es_to_compare.hdf5',
)
# let the comparatier do the auto comparison:
import tessif.parse # nopep8
import functools # nopep8
from tessif.frused.hooks.tsf import reparameterize_components # nopep8
import pandas as pd # nopep8
memory_results = {}
for software in SOFTWARES:
dct = tessif.analyze.trace_memory(
path=os.path.join(write_dir, 'tsf', 'es_to_compare.hdf5'),
parser=tessif.parse.hdf5,
model=software,
hook=hook,
)
memory_df = pd.DataFrame(
data=dct.values(), index=dct.keys(), columns=(software,))
memory_df = memory_df.divide(1e6).round(0)
memory_df.index.name = "Memory [MB]"
memory_df.rename(index={'simulation': 'optimization'}, inplace=True)
csv_path = os.path.join(current_path, "_".join(
[software, "memory_results.csv"]))
memory_df.to_csv(csv_path)
print("memory results obtianed")
timing_results = {}
for software in SOFTWARES:
dct = tessif.analyze.stop_time(
path=os.path.join(write_dir, 'tsf', 'es_to_compare.hdf5'),
parser=tessif.parse.hdf5,
model=software,
measurement='wall',
hook=hook,
)
timings_df = pd.DataFrame(
data=dct.values(), index=dct.keys(), columns=(software,))
timings_df = timings_df.round(1)
timings_df.index.name = "Timings [s]"
timings_df.rename(index={'simulation': 'optimization'}, inplace=True)
csv_path = os.path.join(current_path, "_".join(
[software, "timings_results.csv"]))
timings_df.to_csv(csv_path)
print("timing results obtianed")
Computational Ressources Plots
The computational ressources bar plots from above are created using following code:
from tessif.frused.paths import doc_dir # nopep8
import os # nopep8
import pandas as pd # nopep8
FOLDER = "results"
# SOFTWARES = ('cllp', 'fine', 'ppsa', 'omf',)
SOFTWARES = ('cllp', 'fine', 'ppsa', 'omf',)
# locate the storage directory
current_path = os.path.join(
doc_dir, "source", "getting_started", "examples", "application",
"phd", "model_scenario_combinations", "LossLC", FOLDER
)
memory_results = {}
for software in SOFTWARES:
csv_path = os.path.join(current_path, "_".join(
[software, "memory_results.csv"]))
memory_results[software] = pd.read_csv(
csv_path, index_col=0).to_dict()[software]
memory_df = pd.DataFrame(memory_results)
memory_df.index.name = "Memory [MB]"
csv_path = os.path.join(current_path, "memory_results.csv")
plot_path = os.path.join(current_path, "memory_results.png")
memory_df.to_csv(csv_path)
memory_df.plot(kind="bar", rot=0, figsize=(10, 5)).figure.savefig(plot_path)
timings_results = {}
for software in SOFTWARES:
csv_path = os.path.join(current_path, "_".join(
[software, "timings_results.csv"]))
timings_results[software] = pd.read_csv(
csv_path, index_col=0).to_dict()[software]
timings_df = pd.DataFrame(timings_results)
timings_df.index.name = "Time [s]"
csv_path = os.path.join(current_path, "timings_results.csv")
plot_path = os.path.join(current_path, "timings_results.png")
timings_df.to_csv(csv_path)
timings_df.plot(kind="bar", rot=0, figsize=(10, 5)).figure.savefig(plot_path)