Hello,
I am currently working on a multiperiod-model of a single-family household.
My model contains a heat and battery storage. For both storages I choose the balance to be true, so the storage content at beginning and the end of each period should be the same.
It turned out that this is not the case in the results of my model .
I then assumed that the balanced=True command only influenced the beginning and ending of the first- and last-time interval of the whole optimization, regardless of the periods.
The results did not verify my assumed explanation, as the storage content in the first interval showed that the storages were charged to their maximum capacities and in the Last interval they were emptied out.
So, for my model setting the storages balanced=true had no effect whats ever.
The model in which I initially ran over the issue is rather complex.
I created a minimalistic example that contains an electricity source, a storage and an electricity sink as a multiperiod model with two periods, each period is one year (8760 h) long.
In that minimalistic model the same problem accord.
The code and the input data as below.
#minimalistic example
import os
import pandas as pd
import oemof.solph as solph
from pyomo.environ import Constraint
from pyomo.environ import SolverFactory
# %% (Daten einlesen)
file_path = os.path.dirname(__file__)
file_name = os.path.join(file_path, "input_data_minimalbeispiel.csv")
data = pd.read_csv(file_name, sep=";", decimal=".")
data["date"] = pd.to_datetime(
data["date"],
format="%d.%m.%Y %H:%M"
)
data = data.set_index("date")
full_index = pd.date_range(start="2027-01-01", end="2028-12-31 23:00", freq="h")
full_index = full_index[~((full_index.month == 2) & (full_index.day == 29))]
data.index = full_index
# %% (Perioden: 2 volle Jahre)
periods = [
data.loc["2027"].index,
data.loc["2028"].index,
]
energy_system = solph.EnergySystem(
timeindex=data.index,
timeincrement=[1] * len(data.index),
periods=periods,
infer_last_interval=False,
)
# %% (Komponenten)
ac_bus = solph.Bus(label="ac network")
energy_system.add(ac_bus)
grid = solph.components.Source(
label="grid",
outputs={
ac_bus: solph.Flow(variable_costs=data["el spot price"])
},
)
energy_system.add(grid)
demand = solph.components.Sink(
label="electricity demand",
inputs={
ac_bus: solph.Flow(nominal_capacity=1, fix=data["electricity demand"])
},
)
energy_system.add(demand)
battery = solph.components.GenericStorage(
label="battery",
inputs={
ac_bus: solph.Flow(
nominal_capacity=solph.Investment(ep_costs=0, maximum=10, lifetime=15)
)
},
outputs={
ac_bus: solph.Flow(
nominal_capacity=solph.Investment(ep_costs=0, maximum=10, lifetime=15)
)
},
nominal_storage_capacity=solph.Investment(
ep_costs=100, maximum=20, lifetime=15
),
inflow_conversion_factor=0.95,
outflow_conversion_factor=0.95,
loss_rate=0,
balanced=True,
)
energy_system.add(battery)
# %% (Modell und Loesung)
model = solph.Model(energy_system)
print("\nConstraints im GenericInvestmentStorageBlock:")
blk = model.GenericInvestmentStorageBlock
for c in blk.component_objects(Constraint):
print(" ", c.name, "-> Anzahl Eintraege:", len(c))
blk.initially_empty.deactivate()
solver = SolverFactory("gurobi") # ggf. auf "cbc" o.ae. aendern
solver_results = solver.solve(model, tee=True)
results = solph.processing.results(model)
# %% (Auswertung)
soc = results[(battery, None)]["sequences"]["storage_content"]
t_boundary = len(periods[0]) # erster Zeitschritt von Periode 1
print("\nInvestierte Kapazitaet je Periode:")
for p in range(len(periods)):
invest_p = model.GenericInvestmentStorageBlock.invest[battery, p].value
print(f" Periode {p}: {invest_p:.3f} kWh")
print("\nSpeicherfuellstand (Batterie):")
print(" Start (t=0): ", round(soc.iloc[0], 3))
print(" Periodengrenze (Jahreswechsel 2027/2028):", round(soc.iloc[t_boundary], 3))
print(" Ende (letzter Zeitschritt): ", round(soc.iloc[-1], 3))
Inputdata: input_data_minimalistic_model · GitHub