"""
Christian Klemm - christian.klemm@fh-muenster.de
Gregor Becker - gregor.becker@fh-muenster.de
Oscar Quiroga - oscar.quiroga@fh-muenster.de
"""
import logging
import pandas as pd
from oemof import solph
from matplotlib import pyplot as plt
import os
from program_files.postprocessing.create_results_collecting_data \
import collect_data
from program_files.postprocessing.create_results_prepare_data \
import prepare_data
[docs]
def xlsx(nodes_data: dict, optimization_model: solph.Model, filepath: str) -> None:
"""
Returns model results as xlsx-files.
Saves the in- and outgoing flows of every bus of a given,
optimized energy system as .xlsx file
:param nodes_data: dictionary containing data from excel
model definition file
:type nodes_data: dict
:param optimization_model: optimized energy system
:type optimization_model: oemof.solph.model
:param filepath: path, where the results will be stored
:type filepath: str
"""
results = solph.processing.results(optimization_model)
for i, b in nodes_data["buses"].iterrows():
if b["active"]:
file_path = os.path.join(filepath, "results_" + b["label"] + ".xlsx")
node_results = solph.views.node(results, b["label"])
if "sequences" not in node_results:
logging.warning(f"No sequence results found for bus '{b['label']}', skipping.")
continue
df = node_results["sequences"]
with pd.ExcelWriter(file_path) as writer:
df = df.copy()
# Remove time zone from the index if it exists
if df.index.tz is not None:
df.index = df.index.tz_localize(None)
# Remove column time zone (just in case)
for col in df.columns:
if pd.api.types.is_datetime64_any_dtype(df[col]):
try:
df[col] = df[col].dt.tz_localize(None)
except Exception:
pass
df.to_excel(writer, sheet_name="Sheet1")
[docs]
def charts(nodes_data: dict, optimization_model: solph.Model,
energy_system: solph.EnergySystem) -> None:
"""
Plots model results in- and outgoing flows of every bus of a
given, optimized energy system (based on matplotlib)
:param nodes_data: dictionary containing data from excel \
model definition file
:type nodes_data: dict
:param optimization_model: optimized energy system
:type optimization_model: oemof.solph.Model
:param energy_system: original (unoptimized) energy system
:type energy_system: oemof.solph.Energysystem
"""
# rename variables
esys = energy_system
results = solph.processing.results(optimization_model)
for num, bus in nodes_data["buses"].iterrows():
if bus["active"]:
logging.info('\t ' + 56 * '*')
logging.info(" " + "RESULTS: " + bus["label"])
bus = solph.views.node(results, bus["label"])
logging.info("\t" + bus["sequences"].sum())
fig, ax = plt.subplots(figsize=(10, 5))
bus["sequences"].plot(ax=ax)
ax.legend(
loc="upper center",
prop={"size": 8},
bbox_to_anchor=(0.5, 1.4),
ncol=2
)
fig.subplots_adjust(top=0.7)
plt.show()
esys.results["main"] = solph.processing.results(optimization_model)
esys.results["meta"] = solph.processing.meta_results(optimization_model)
esys.dump(dpath=None, filename=None)
[docs]
class Results:
"""
Returns a list of all defined components with the following
information:
+------------+----------------------------------------------+
|component | information |
+------------+----------------------------------------------+
|sinks | Total Energy Demand |
+------------+----------------------------------------------+
|sources | Total Energy Input, Max. Capacity, |
| | Variable Costs, Periodical Costs |
+------------+----------------------------------------------+
|transformers| Total Energy Output, Max. Capacity, |
| | Variable Costs, Investment Capacity, |
| | Periodical Costs |
+------------+----------------------------------------------+
|storages | Energy Output, Energy Input, Max. Capacity,|
| | Total variable costs, Investment Capacity, |
| | Periodical Costs |
+------------+----------------------------------------------+
|links | Total Energy Output |
+------------+----------------------------------------------+
Furthermore, a list of recommended investments is printed.
The algorithm uses the following steps:
1. logging the component type for example "sinks"
2. creating pandas dataframe out of the results of the
optimization consisting of every single flow in/out
a component
3. calculating the investment and the costs regarding
the flows
4. adding the component to the list of components (loc)
which is part of the plotly dash and is the content
of components.csv
:param nodes_data: dictionary containing data from excel \
model definition file
:type nodes_data: dict
:param optimization_model: optimized energy system
:type optimization_model: oemof.solph.Model
:param energy_system: original (unoptimized) energy system
:type energy_system: oemof.solph.Energysystem
:param result_path: Path where the results are saved.
:type result_path: str
:param variable_cost_factor: factor that considers the data_preparation_algorithms,
can be used to scale the results up for a year
:type variable_cost_factor: float
:param console_log: boolean which decides rather the results \
will be logged in the console or not
:type console_log: bool
:param cluster_dh: boolean which decides rather the thermal \
network was spatially clustered or not
:type cluster_dh: bool
"""
results = None
esys = None
comp_capacity = None
df_list_of_components = None
df_result_table = None
def __init__(
self,
nodes_data: dict,
optimization_model: solph.Model,
energy_system: solph.EnergySystem,
result_path: str,
variable_cost_factor: float,
console_log: bool,
cluster_dh: bool,
):
"""
Inits the Results class.
"""
# remove all old entries from method intern variables
investments_to_be_made = {}
# define class variables
self.esys = energy_system
self.results = solph.processing.results(optimization_model)
# collect the energy system results which have to be extracted
# from the component specific result object
comp_dict, total_demand, total_usage = collect_data(
nodes_data=nodes_data,
results=self.results,
esys=self.esys,
result_path=result_path,
variable_cost_factor=variable_cost_factor
)
(
loc,
total_periodical_costs,
total_variable_costs,
total_constraint_costs,
df_result_table,
total_demand,
flow_info_df,
) = prepare_data(comp_dict=comp_dict,
total_demand=total_demand,
nodes_data=nodes_data,
variable_cost_factor=variable_cost_factor)
# SUMMARY
meta_results = solph.processing.meta_results(optimization_model)
meta_results_objective = meta_results["objective"]
# Importing time system parameters from the model definition
ts = next(nodes_data["energysystem"].iterrows())[1]
temp_resolution = ts["temporal resolution"]
start_date = ts["start date"]
end_date = ts["end date"]
df_summary = pd.DataFrame(
[
[
start_date,
end_date,
temp_resolution,
round(meta_results_objective, 2),
round(total_constraint_costs, 2),
round(total_variable_costs, 2),
round(total_periodical_costs, 2),
round(total_demand, 2),
round(total_usage, 2),
variable_cost_factor,
]
],
columns=[
"Start Date",
"End Date",
"Resolution",
"Total System Costs",
"Total Constraint Costs",
"Total Variable Costs",
"Total Periodical Costs",
"Total Energy Demand",
"Total Energy Usage",
"Variable Cost Factor"
],
)
# Dataframes are exported as csv for further processing
loc.to_csv(result_path + "/components.csv", index=False)
df_result_table = df_result_table.rename_axis("date")
df_result_table.to_csv(result_path + "/results.csv")
df_summary.to_csv(result_path + "/summary.csv", index=False)
flow_info_df.to_csv(result_path + "/flow_information.csv", index=False)
logging.info(" " + "Successfully prepared results...")