Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ examples = []
importer = ["pyproj"]
test = [
"pytest",
"tespy",
"coverage",
"pvlib",
"demandlib",
Expand Down
27 changes: 12 additions & 15 deletions src/oemof/eesyplan/components/converters/HeatPump.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ class HeatPump(Converter):
def __init__(
self,
name,
bus_in_heat,
project_data,
installed_capacity,
bus_in_electricity,
bus_out_heat,
project_data,
bus_in_heat=None,
age_installed=0,
installed_capacity=0,
capex_fix=1000,
capex_var=1000,
opex_var=0.01,
opex_fix=10,
Expand Down Expand Up @@ -50,9 +49,6 @@ def __init__(
Number of years the asset has already been in operation.
installed_capacity : float, default=0
Already existing installed capacity.
capex_fix : float, default=1000
Specific investment costs of the asset related to the
installed capacity (CAPEX).
capex_var : float, default=1000
Specific investment costs of the asset related to the
installed capacity (CAPEX).
Expand All @@ -77,14 +73,13 @@ def __init__(
Examples
--------
>>> from oemof.eesyplan import Project
>>> from oemof.solph import Bus
>>> el_bus = Bus(label="electricity_bus")
>>> ambient_heat_bus = Bus(label="ambient_heat_bus")
>>> heat_bus = Bus(label="heat_bus")
>>> from oemof.eesyplan import CarrierBus
>>> el_bus = CarrierBus(name="electricity_bus")
>>> ambient_heat_bus = CarrierBus(name="ambient_heat_bus")
>>> heat_bus = CarrierBus(name="heat_bus")
>>> my_heat_pump = HeatPump(
... name="air_source_heat_pump",
... bus_in_electricity=el_bus,
... bus_in_heat=ambient_heat_bus,
... bus_out_heat=heat_bus,
... installed_capacity=15,
... cop=3.5,
Expand Down Expand Up @@ -122,7 +117,7 @@ def __init__(
project_data=project_data,
)

inputs = {bus_in_heat: Flow(), bus_in_electricity: Flow()}
inputs = {bus_in_electricity: Flow()}

outputs = {
bus_out_heat: Flow(
Expand All @@ -133,9 +128,12 @@ def __init__(

conversion_factors = {
bus_in_electricity: 1 / cop,
bus_in_heat: (cop - 1) / cop,
}

if bus_in_heat is not None:
conversion_factors[bus_in_heat] = (cop - 1) / cop
inputs[bus_in_heat] = Flow()

super().__init__(
label=name,
outputs=outputs,
Expand All @@ -146,7 +144,6 @@ def __init__(
self.name = name
self.age_installed = age_installed
self.installed_capacity = installed_capacity
self.capex_fix = capex_fix
self.capex_var = capex_var
self.opex_var = opex_var
self.opex_fix = opex_fix
Expand Down
155 changes: 155 additions & 0 deletions src/oemof/eesyplan/importer/cop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import numpy as np

try:
from tespy.components import Compressor
from tespy.components import CycleCloser
from tespy.components import SimpleHeatExchanger
from tespy.components import Valve
from tespy.connections import Connection
from tespy.networks import Network
except (ImportError, ModuleNotFoundError):
Network = None


def calculate_cop_simple(
temperature_source, temperature_supply, quality_factor
):
"""

Parameters
----------
temperature_source : float or array-like
temperature_supply : float or array-like
quality_factor : float or array-like

Returns
-------
float or array-like

Examples
--------
>>> round(calculate_cop_simple(10.0, 55.0, 0.5), 2)
3.65

"""
temperature_source = np.array(temperature_source)
temperature_supply = np.array(temperature_supply)
quality_factor = np.array(quality_factor)

cop = (
(temperature_supply + 273.15)
* quality_factor
/ (temperature_supply - temperature_source)
)
if isinstance(cop, np.float64):
return cop.item()

return cop


def calculate_cop_tespy(
temperature_source,
temperature_supply,
refrigerant="R290",
capacity=1000,
pressure_loss_factor_hex=1,
eta_s=0.55,
):
"""
Temperature input must have the same length.

Parameters
----------
temperature_source
temperature_supply
capacity
refrigerant
pressure_loss_factor_hex
eta_s

Returns
-------

Examples
--------
>>> c = calculate_cop_simple(10.0, [35, 45, 55], 0.5)
>>> [round(float(val), 2) for val in c]
[6.16, 4.54, 3.65]
>>> c = calculate_cop_tespy([10.0] * 3, [35, 45, 55])
>>> [round(float(val), 2) for val in c]
[6.33, 4.54, 3.52]
>>> c = calculate_cop_tespy([10.0] * 3, [35, 45, 55], refrigerant="R134a")
>>> [round(float(val), 2) for val in c]
[6.42, 4.62, 3.59]
>>> round(calculate_cop_simple(10, 40, 0.5), 2)
5.22
>>> round(calculate_cop_tespy(10, 40), 2)
5.29
"""

if Network is None:
msg = (
"TESPy is required to use this function.\n"
"Please install the tespy package: 'pip install tespy'"
)
raise ModuleNotFoundError(msg)

if isinstance(temperature_source, (float | int)):
temperature_source = [temperature_source]
temperature_supply = [temperature_supply]
length = 1
else:
length = len(temperature_source)

temperature_source = np.array(temperature_source)
temperature_supply = np.array(temperature_supply)

# create a network object with R134a as fluid
my_plant = Network()

# set the unitsystem for temperatures to °C and for pressure to bar
my_plant.units.set_defaults(
temperature="degC",
pressure="bar",
pressure_difference="bar",
enthalpy="kJ/kg",
heat="kW",
power="kW",
)

cc = CycleCloser("cycle closer")

# heat sink
co = SimpleHeatExchanger("condenser")
# heat source
ev = SimpleHeatExchanger("evaporator")

va = Valve("expansion valve")
cp = Compressor("compressor")

# connections of heat pump
c1 = Connection(cc, "out1", ev, "in1", label="1")
c2 = Connection(ev, "out1", cp, "in1", label="2")
c3 = Connection(cp, "out1", co, "in1", label="3")
c4 = Connection(co, "out1", va, "in1", label="4")
c0 = Connection(va, "out1", cc, "in1", label="0")

# this line is crutial: you have to add all connections to your network
my_plant.add_conns(c1, c2, c3, c4, c0)

co.set_attr(pr=pressure_loss_factor_hex, Q=capacity * -1)
ev.set_attr(pr=pressure_loss_factor_hex)
cp.set_attr(eta_s=eta_s)

def get_cop(c_src, c_sup, n):
c_src.set_attr(T=temperature_source[n], x=1, fluid={refrigerant: 1})
c_sup.set_attr(T=temperature_supply[n], x=0)

my_plant.solve("design", print_results=False)
return abs(co.Q.val) / cp.P.val

cops = [get_cop(c2, c4, n) for n in range(length)]

if len(cops) == 1:
cops = float(cops[0])
return cops
2 changes: 1 addition & 1 deletion tests/test_constraints/test_heat_pump.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ def test_heat_pump_investment():
es.add(el_bus, ambient_bus, heat_bus)
heat_pump = HeatPump(
name="air_source_heat_pump",
installed_capacity=0,
bus_in_electricity=el_bus,
bus_in_heat=ambient_bus,
bus_out_heat=heat_bus,
maximum_capacity=15,
optimize_cap=True,
capex_var=100,
capex_fix=10,
opex_var=-10,
opex_fix=1,
cop=[3.5, 3.2] * 5,
Expand Down
31 changes: 31 additions & 0 deletions tests/test_importer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import importlib
import sys
from unittest.mock import patch

import pytest

from oemof.eesyplan.importer import cop


def test_tespy_not_installed():
"""Set Network to None."""
with patch.object(cop, "Network", None):
with pytest.raises(ModuleNotFoundError, match="TESPy is required"):
cop.calculate_cop_tespy(10, 40)


def test_tespy_not_installed_via_import():
"""As if tespy would not exist."""
with patch.dict(
sys.modules,
{
"tespy": None,
"tespy.components": None,
"tespy.connections": None,
"tespy.networks": None,
},
):
importlib.reload(cop)

with pytest.raises(ModuleNotFoundError, match="TESPy is required"):
cop.calculate_cop_tespy(10, 40)
Loading