Time Series Aggregation¶
In this example, we are going to explore different ways to cluster the temporal resolution of PyPSA models, and what impact they have on the optimisation results and solving times. Using an hourly resolved variant of the single-node capacity expansion example, we will compare three different approaches to reduce the number of time steps in the model:
- Sampling: Selecting a subset of the given snapshots based on a given frequency,
- Averaging: Aggregating the snapshots by averaging them over a given frequency, and
- Segmentation: Clustering the snapshots into segments of a given frequency and using
tsamlibrary.
We start with the usual imports and loading the hourly resolved model.
import logging
import time
import pandas as pd
import pypsa
logging.getLogger().setLevel(logging.WARNING)
template_n = pypsa.Network(
"https://tubcloud.tu-berlin.de/s/4ra3NKrLGzE42of/download/model-energy-hourly.nc"
)
INFO:pypsa.network.io:Retrieving network data from https://tubcloud.tu-berlin.de/s/4ra3NKrLGzE42of/download/model-energy-hourly.nc.
WARNING:pypsa.network.io:Importing network from PyPSA version v0.35.0 while current version is v1.2.0. Read the release notes at `https://go.pypsa.org/release-notes` to prepare your network for import.
INFO:pypsa.network.io:Imported network 'Unnamed Network' has buses, carriers, generators, links, loads, storage_units, stores
Since we also want to monitor the solving times, we will use a small utility function that wraps around the solving process and returns the seconds it took to solve the model:
def time_it(func, *args, **kwargs):
"""Time the execution of a function and return the elapsed time in seconds."""
start_time = time.time()
result = func(*args, **kwargs)
elapsed_time = time.time() - start_time
return result, elapsed_time
logging.getLogger().setLevel(logging.WARNING)
Hourly Baseline¶
Additionally, we need a baseline model to compare aggregated models against. We will use the hourly resolved model for this.
n_hourly = template_n.copy()
_, s_hourly = time_it(n_hourly.optimize, solver_name="gurobi")
s_hourly
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 62%|██████▏ | 13/21 [00:00<00:00, 129.66it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 105.14it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 310.46it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-9ozye4he.lp
Reading time = 0.22 seconds
obj: 192726 rows, 87606 columns, 372396 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
30.136342525482178
Sampling¶
We will start with the sampling approach, which is the simplest one. We simply select every $N$-th snapshot from the model. The important part here is that we need to adjust the snapshot weightings accordingly, as each remaining snapshot now represents $N$ hours. We iterate over N from 2 to 11, i.e. from 2-hourly to 11-hourly resolved models.
sampling_n = {1: n_hourly}
sampling_s = {1: s_hourly}
for resolution in range(2, 12):
n = template_n.cluster.temporal.downsample(resolution)
_, s = time_it(n.optimize, solver_name="gurobi")
sampling_n[resolution] = n
sampling_s[resolution] = s
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 90%|█████████ | 19/21 [00:00<00:00, 173.66it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 164.28it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 381.02it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-sz23tjxe.lp
Reading time = 0.10 seconds
obj: 96366 rows, 43806 columns, 186198 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 95%|█████████▌| 20/21 [00:00<00:00, 198.46it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 192.00it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 407.89it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-dbl76u2x.lp
Reading time = 0.07 seconds
obj: 64246 rows, 29206 columns, 124144 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 216.15it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 382.59it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-w6thd3hz.lp
Reading time = 0.05 seconds
obj: 48186 rows, 21906 columns, 93110 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 224.08it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 428.56it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-0mk0gyey.lp
Reading time = 0.04 seconds
obj: 38550 rows, 17526 columns, 74479 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 222.21it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 419.03it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-syvksti3.lp
Reading time = 0.03 seconds
obj: 32126 rows, 14606 columns, 62068 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 239.05it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 428.59it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-up514xpx.lp
Reading time = 0.03 seconds
obj: 27550 rows, 12526 columns, 53225 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 247.21it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 441.56it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-i66m_d7b.lp
Reading time = 0.03 seconds
obj: 24096 rows, 10956 columns, 46588 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-463711ds.lp
Reading time = 0.02 seconds
obj: 21434 rows, 9746 columns, 41420 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-36veaujf.lp
Reading time = 0.02 seconds
obj: 19278 rows, 8766 columns, 37242 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-7fa8ujc_.lp
Reading time = 0.02 seconds
obj: 17540 rows, 7976 columns, 33888 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
Averaging¶
The averaging approach also has equal snapshot durations, but instead of selecting data from every $N$-th snapshots, we average time series data for every $N$ snapshots. This means that the resulting model has $N$ times fewer snapshots, but each snapshot represents the average of $N$ original snapshots. Again, we need to adjust the snapshot weightings accordingly.
averaging_n = {1: n_hourly}
averaging_s = {1: s_hourly}
for resolution in range(2, 12):
n = template_n.cluster.temporal.resample(f"{resolution}h")
_, s = time_it(n.optimize, solver_name="gurobi")
averaging_n[resolution] = n
averaging_s[resolution] = s
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 90%|█████████ | 19/21 [00:00<00:00, 165.06it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 157.81it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 358.52it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-fn8yfnu6.lp
Reading time = 0.10 seconds
obj: 96366 rows, 43806 columns, 186415 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 90%|█████████ | 19/21 [00:00<00:00, 189.07it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 181.64it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 385.03it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-m3b8r5uv.lp
Reading time = 0.07 seconds
obj: 64246 rows, 29206 columns, 124352 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 201.30it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 199.54it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 412.79it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-b9vfvoal.lp
Reading time = 0.05 seconds
obj: 48186 rows, 21906 columns, 93397 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 224.71it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 429.32it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-mhbpy9oh.lp
Reading time = 0.04 seconds
obj: 38550 rows, 17526 columns, 74771 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 232.13it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 434.10it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-m2cb2l5o.lp
Reading time = 0.03 seconds
obj: 32126 rows, 14606 columns, 62364 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 95%|█████████▌| 20/21 [00:00<00:00, 193.93it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 188.29it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 364.54it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-c6422g3b.lp
Reading time = 0.03 seconds
obj: 27550 rows, 12526 columns, 53538 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 241.05it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 426.93it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-dtnbuqk7.lp
Reading time = 0.03 seconds
obj: 24096 rows, 10956 columns, 46953 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-y2gl9ks6.lp
Reading time = 0.02 seconds
obj: 21434 rows, 9746 columns, 41730 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-z2qiqhpc.lp
Reading time = 0.02 seconds
obj: 19278 rows, 8766 columns, 37563 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-592zxo96.lp
Reading time = 0.02 seconds
obj: 17540 rows, 7976 columns, 34205 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
Segmentation¶
The segmentation approach is more complex. It uses a separate library called tsam to cluster the snapshots into segments of varying lengths. The sequence of snapshots is preserved as segments are only formed from neighbouring snapshots based on their similarity. For measuring similarity, it is advisable to normalise the time series data. This approach promises to capture the temporal patterns more effectively, as it can opt for higher resolution during periods of high variability and lower resolution during periods with low variability. The snapshot weightings are adjusted based on the number of snapshots in each segment.
segmentation_n = {1: n_hourly}
segmentation_s = {1: s_hourly}
for resolution in range(2, 12):
# calculate number of segments equivalent to resolution
segments = int(8760 / resolution)
n = template_n.cluster.temporal.segment(segments)
# run optimization
_, s = time_it(n.optimize, solver_name="gurobi")
segmentation_n[resolution] = n
segmentation_s[resolution] = s
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 86%|████████▌ | 18/21 [00:00<00:00, 174.18it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 145.98it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 338.99it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-puta36co.lp
Reading time = 0.10 seconds
obj: 96366 rows, 43806 columns, 187272 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 90%|█████████ | 19/21 [00:00<00:00, 170.00it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 164.73it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 383.37it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-46vyqwq5.lp
Reading time = 0.07 seconds
obj: 64246 rows, 29206 columns, 125094 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 203.93it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 202.14it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 415.46it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-06e3tsyy.lp
Reading time = 0.05 seconds
obj: 48186 rows, 21906 columns, 93920 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 204.50it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 202.73it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 416.15it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-1y46z35d.lp
Reading time = 0.04 seconds
obj: 38550 rows, 17526 columns, 75193 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 221.38it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 427.72it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-7td5lfyn.lp
Reading time = 0.03 seconds
obj: 32126 rows, 14606 columns, 62672 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 232.89it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 438.77it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-h2ec_9r9.lp
Reading time = 0.03 seconds
obj: 27528 rows, 12516 columns, 53707 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Writing constraints.: 0%| | 0/21 [00:00<?, ?it/s]
Writing constraints.: 100%|██████████| 21/21 [00:00<00:00, 238.50it/s]
Writing continuous variables.: 0%| | 0/11 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 11/11 [00:00<00:00, 444.66it/s]
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-hg8nd3e5.lp
Reading time = 0.03 seconds
obj: 24096 rows, 10956 columns, 47017 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-dq6gftwe.lp
Reading time = 0.02 seconds
obj: 21412 rows, 9736 columns, 41782 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-33gjn9s5.lp
Reading time = 0.02 seconds
obj: 19278 rows, 8766 columns, 37625 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
/tmp/ipykernel_8271/4243218267.py:4: FutureWarning: The default value of `include_objective_constant` will change from True to False in version 2.0. Set `include_objective_constant` explicitly to suppress this warning. Using False improves LP numerical conditioning by not including the objective constant as a variable. result = func(*args, **kwargs)
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2537914
Academic license 2537914 - for non-commercial use only - registered to l.___@tu-berlin.de
Read LP format model from file /tmp/linopy-problem-mm9re1b3.lp
Reading time = 0.02 seconds
obj: 17518 rows, 7966 columns, 34194 nonzeros
Set parameter LogToConsole to value 0
Warning: environment still referenced so free is deferred (Continue to use WLS)
Now before we go ahead with the evaluation of the different approaches, let's quickly glance at the distribution of snapshot durations obtained from the segmentation approach for a resolution equivalent to a 3-hourly model. We can see quite some variability in the segment length.
segmentation_n[3].snapshot_weightings.generators.value_counts().sort_index(
ascending=True
).plot.bar(ylabel="snapshots [number]", xlabel="snapshot duration [h]")
<Axes: xlabel='snapshot duration [h]', ylabel='snapshots [number]'>
Evaluation¶
Let's start our evaluation with a look at the solving times. We can see that across all approaches, the solving times quickly decay, especially as we go from hourly to 2-hourly resolved models and decrease less substantially afterwards.
pd.Series(sampling_s).plot(label="sampling", legend=True)
pd.Series(averaging_s).plot(label="averaging", legend=True)
pd.Series(segmentation_s).plot(
label="segmentation", ylabel="time [s]", xlabel="resolution [h]", legend=True
)
<Axes: xlabel='resolution [h]', ylabel='time [s]'>
Furthermore, we compare the relative error in total system costs compared to the hourly resolved model. We can see how the segmentation approach remains more stable than the other two approaches, especially for lower resolutions. Even with 11-hourly equivalent resolution, the segmentation approach only has a relative error of -1% compared to the hourly resolved model (i.e. it appears to be 1% cheaper). Similar patterns can be observed for the relative error in the total installed capacity of solar and batteries, two technologies that are particularly sensitive to the temporal resolution of the model.
def tsc(n):
return (n.statistics.capex().sum() + n.statistics.opex().sum()) / 1e9
pd.concat(
[
pd.Series({("sampling", res): tsc(n) for res, n in sampling_n.items()}),
pd.Series({("averaging", res): tsc(n) for res, n in averaging_n.items()}),
pd.Series({("segmentation", res): tsc(n) for res, n in segmentation_n.items()}),
]
).unstack(0).div(tsc(n_hourly)).sub(1).mul(100).plot(
ylabel="relative objective error [%]", xlabel="resolution [h]", legend=True
)
<Axes: xlabel='resolution [h]', ylabel='relative objective error [%]'>
def solar(n):
return n.generators.loc["solar", "p_nom_opt"]
pd.concat(
[
pd.Series({("sampling", res): solar(n) for res, n in sampling_n.items()}),
pd.Series({("averaging", res): solar(n) for res, n in averaging_n.items()}),
pd.Series(
{("segmentation", res): solar(n) for res, n in segmentation_n.items()}
),
]
).unstack(0).div(solar(n_hourly)).sub(1).mul(100).plot(
ylabel="relative solar capacity error [%]", xlabel="resolution [h]", legend=True
)
<Axes: xlabel='resolution [h]', ylabel='relative solar capacity error [%]'>
def battery(n):
return n.storage_units.loc["battery storage", "p_nom_opt"]
pd.concat(
[
pd.Series({("sampling", res): battery(n) for res, n in sampling_n.items()}),
pd.Series({("averaging", res): battery(n) for res, n in averaging_n.items()}),
pd.Series(
{("segmentation", res): battery(n) for res, n in segmentation_n.items()}
),
]
).unstack(0).div(battery(n_hourly)).sub(1).mul(100).plot(
ylabel="relative battery capacity error [%]", xlabel="resolution [h]", legend=True
)
<Axes: xlabel='resolution [h]', ylabel='relative battery capacity error [%]'>