oemof-solph model with minimal load#
In this section we are looking into the introduction of minimal load in the oemof-solph
model. Until now, we assumed
the heat pump can deliver any amount of heat up to its nominal capacity. This assumption holds especially in large scale
energy systems, where single plant instances do not affect the overall outcomes and part load operation blurs in the
system, in small scale systems this might not be the case. Therefore, we have a look how a minimal load affects our
model.
We recreate the latest setup, where we combine the TESPy simulation outcome with the energy system. Then we add a heat pump which, if operated, must at least provide a heat load of 50 % of its nominal capacity.
from utilities import load_input_data, create_energy_system_stub
input_data = load_input_data().head(24*2)
es, bus_electricity, bus_heat_35C = create_energy_system_stub(input_data)
from utilities import load_tespy_cop
tespy_cop = load_tespy_cop()
input_data["simple TESPy COP"] = input_data["Ambient temperature (d°C)"].map(tespy_cop["COP"])
The important modification we have to apply to our heat pump is constraining the heat production with a minimum value
and using a NonConvex
flow instead of a Flow
, which introduces a binary variable. All other parts remain untouched.
import oemof.solph as solph
hp_thermal_power = 9.1 # kW
cop = input_data["simple TESPy COP"][:-1]
heat_pump = solph.components.Converter(
label="heat pump",
inputs={bus_electricity: solph.Flow()},
outputs={
bus_heat_35C: solph.Flow(
nominal_value=hp_thermal_power,
nonconvex=solph.NonConvex(),
min=0.5,
)
},
conversion_factors={
bus_electricity: 1 / cop,
bus_heat_35C: 1,
},
)
es.add(heat_pump)
We can again run our model and have a look at the results.
model = solph.Model(energysystem=es)
model.solve()
results = solph.processing.results(model)
FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
From Fig. 11 you can see how the minimum load restrictions impacts the operation of the heat
pump. While the storage was barely used in the first two examples, now heat demand below the minimum heat pump load
cannot be met directly from the heat pump, but has to be buffered by the storage. Still, the storage operation is held
at a minimum, to reduce the time dependent storage losses. The change in electricity consumption is larger compared to
our previous model additions, i.e. it changes from 14.03
kWh
to 14.23 kWh.
from matplotlib import pyplot as plt
from utilities import sumarise_solph_results
fig, electricity_total = sumarise_solph_results(results)
plt.close()
Electricity demand: 14.2 kWh