Building Energy System#
Optimal combination of segments and periods for building energy supply systems.
Author: Leander Kotzur
Import pandas and the relevant time series aggregation class
[1]:
%load_ext autoreload
%autoreload 2
import pandas as pd
import plotly.express as px
import plotly.io as pio
import tsam
from tsam import ClusterConfig, SegmentConfig
from tsam.tuning import find_pareto_front
pio.renderers.default = "notebook"
Input data#
Read in time series from testdata.csv with pandas
[2]:
raw = pd.read_csv("testdata.csv", index_col=0)
raw = raw.rename(
columns={
"T": "Temperature [°C]",
"Load": "Load [kW]",
"Wind": "Wind [m/s]",
"GHI": "Solar [W/m²]",
}
)
[3]:
raw = raw.drop(
columns=[
"Wind [m/s]",
],
)
Use tsam’s built-in heatmap plotting for visual comparison of the time series
Plot an example series - in this case the temperature
[4]:
# Original data heatmaps using tsam.unstack_to_periods() with plotly
unstacked = tsam.unstack_to_periods(raw, period_duration=24)
for col in raw.columns:
px.imshow(
unstacked[col].values.T,
labels={"x": "Day", "y": "Hour", "color": col},
title=f"Original {col}",
aspect="auto",
).show()
Tune a hierarchical aggregation with segments in combination with distribution representation#
Use the new find_pareto_front() function to explore the Pareto-optimal combinations.
[5]:
pareto_results = find_pareto_front(
raw,
period_duration=24,
max_timesteps=100,
cluster=ClusterConfig(
method="hierarchical",
representation="distribution",
),
n_jobs=-1,
)
Building Pareto front: 100%|██████████| 100/100 [00:42<00:00, 2.37it/s]
And determine the pareto optimal aggregation up to 100 total time steps. This may take some time…
[6]:
# Show the last result in the Pareto front
last_result = pareto_results[-1]
print(
f"Final configuration: {last_result.n_clusters} periods, {last_result.n_segments} segments"
)
Final configuration: 20 periods, 5 segments
And show the results for the last aggregation
[7]:
# Reconstruct the data from the last Pareto result
reconstructed = last_result.reconstructed
[8]:
# Reconstructed data heatmaps from last tuned aggregation
unstacked_recon = tsam.unstack_to_periods(reconstructed, period_duration=24)
for col in reconstructed.columns:
px.imshow(
unstacked_recon[col].values.T,
labels={"x": "Day", "y": "Hour", "color": col},
title=f"Reconstructed {col}",
aspect="auto",
).show()
[9]:
last_result.n_segments
[9]:
5
[10]:
last_result.n_clusters
[10]:
20
[11]:
# Example with specific configuration using distribution_minmax representation
result = tsam.aggregate(
raw,
n_clusters=14,
period_duration=24,
cluster=ClusterConfig(
method="hierarchical",
representation="distribution_minmax",
),
segments=SegmentConfig(n_segments=8),
preserve_column_means=False,
)
[12]:
# Reconstructed data heatmaps with 8 segments and 14 periods
recon = result.reconstructed
unstacked_recon2 = tsam.unstack_to_periods(recon, period_duration=24)
for col in recon.columns:
px.imshow(
unstacked_recon2[col].values.T,
labels={"x": "Day", "y": "Hour", "color": col},
title=f"Reconstructed {col} (8 seg, 14 periods)",
aspect="auto",
).show()