Skip to content

Commit

Permalink
Solve issue 276
Browse files Browse the repository at this point in the history
  • Loading branch information
wouterpeere committed Jul 2, 2024
1 parent 7ed2da3 commit 5b57c27
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 103 deletions.
38 changes: 32 additions & 6 deletions GHEtool/Borefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -1824,7 +1824,9 @@ def optimise_load_profile_power(
SCOP: float = 10 ** 6,
SEER: float = 10 ** 6,
temperature_threshold: float = 0.05,
use_hourly_resolution: bool = True
use_hourly_resolution: bool = True,
max_peak_heating: float = None,
max_peak_cooling: float = None
) -> tuple[HourlyGeothermalLoad, HourlyGeothermalLoad]:
"""
This function optimises the load based on the given borefield and the given hourly load.
Expand All @@ -1849,13 +1851,16 @@ def optimise_load_profile_power(
use_hourly_resolution : bool
If use_hourly_resolution is used, the hourly data will be used for this optimisation. This can take some
more time than using the monthly resolution, but it will give more accurate results.
max_peak_heating : float
The maximum peak power for geothermal heating [kW]
max_peak_cooling : float
The maximum peak power for geothermal cooling [kW]
Returns
-------
tuple [HourlyGeothermalLoad, HourlyGeothermalLoad]
borefield load (secundary), external load (secundary)
Raises
------
ValueError
Expand Down Expand Up @@ -1891,13 +1896,18 @@ def optimise_load_profile_power(
init_peak_heating: float = self.load.max_peak_heating
init_peak_cooling: float = self.load.max_peak_cooling

# correct for max peak powers
if max_peak_heating is not None:
init_peak_heating = min(init_peak_heating, max_peak_heating * (1 - 1 / SCOP))

Check warning on line 1901 in GHEtool/Borefield.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/Borefield.py#L1901

Added line #L1901 was not covered by tests
if max_peak_cooling is not None:
init_peak_cooling = min(init_peak_cooling, max_peak_cooling * (1 + 1 / SEER))

Check warning on line 1903 in GHEtool/Borefield.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/Borefield.py#L1903

Added line #L1903 was not covered by tests

# peak loads for iteration
peak_heat_load_geo: float = init_peak_heating
peak_cool_load_geo: float = init_peak_cooling

# set iteration criteria
cool_ok, heat_ok = False, False

while not cool_ok or not heat_ok:
# limit the primary geothermal heating and cooling load to peak_heat_load_geo and peak_cool_load_geo
self.load.set_hourly_cooling(np.minimum(peak_cool_load_geo, primary_geothermal_load.hourly_cooling_load))
Expand Down Expand Up @@ -1931,7 +1941,7 @@ def optimise_load_profile_power(
cool_ok = True
else:
cool_ok = True

print(peak_heat_load_geo)
# calculate the resulting secundary hourly profile that can be put on the borefield
secundary_borefield_load = HourlyGeothermalLoad(simulation_period=building_load.simulation_period)
secundary_borefield_load.set_hourly_cooling(self.load.hourly_cooling_load / (1 + 1 / SEER))
Expand All @@ -1957,6 +1967,8 @@ def optimise_load_profile_energy(
SCOP: float = 10 ** 6,
SEER: float = 10 ** 6,
temperature_threshold: float = 0.05,
max_peak_heating: float = None,
max_peak_cooling: float = None
) -> tuple[HourlyGeothermalLoadMultiYear, HourlyGeothermalLoadMultiYear]:
"""
This function optimises the load based on the given borefield and the given hourly load.
Expand All @@ -1978,6 +1990,10 @@ def optimise_load_profile_energy(
temperature_threshold : float
The maximum allowed temperature difference between the maximum and minimum fluid temperatures and their
respective limits. The lower this threshold, the longer the convergence will take.
max_peak_heating : float
The maximum peak power for geothermal heating [kW]
max_peak_cooling : float
The maximum peak power for geothermal cooling [kW]
Returns
-------
Expand Down Expand Up @@ -2007,10 +2023,20 @@ def optimise_load_profile_energy(
use_constant_Rb_backup = self.borehole.use_constant_Rb
self.Rb = self.borehole.get_Rb(depth, self.D, self.r_b, self.ground_data.k_s)

# set max peak values
init_peak_heating = building_load.hourly_heating_load.copy() * (1 - 1 / SCOP)
init_peak_cooling = building_load.hourly_cooling_load.copy() * (1 + 1 / SEER)

# correct for max peak powers
if max_peak_heating is not None:
init_peak_heating = np.clip(init_peak_heating, None, max_peak_heating * (1 - 1 / SCOP))

Check warning on line 2032 in GHEtool/Borefield.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/Borefield.py#L2032

Added line #L2032 was not covered by tests
if max_peak_cooling is not None:
init_peak_cooling = np.clip(init_peak_cooling, None, max_peak_cooling * (1 + 1 / SEER))

Check warning on line 2034 in GHEtool/Borefield.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/Borefield.py#L2034

Added line #L2034 was not covered by tests

# load hourly heating and cooling load and convert it to geothermal loads
primary_geothermal_load = HourlyGeothermalLoad(simulation_period=building_load.simulation_period)
primary_geothermal_load.set_hourly_cooling(building_load.hourly_cooling_load.copy() * (1 + 1 / SEER))
primary_geothermal_load.set_hourly_heating(building_load.hourly_heating_load.copy() * (1 - 1 / SCOP))
primary_geothermal_load.set_hourly_heating(init_peak_heating)
primary_geothermal_load.set_hourly_cooling(init_peak_cooling)

# set relation qh-qm
nb_points = 100
Expand Down
11 changes: 8 additions & 3 deletions GHEtool/test/methods/TestMethodClass.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ class OptimiseLoadProfileObject:

def __init__(self, borefield: Borefield, load, depth: float, SCOP: float, SEER: float, percentage_heating: float,
percentage_cooling: float, peak_heating_geo: float, peak_cooling_geo: float, peak_heating_ext: float,
peak_cooling_ext: float, name: str = "", power: bool = True, hourly: bool = True):
peak_cooling_ext: float, name: str = "", power: bool = True, hourly: bool = True,
max_peak_heating: float = None,
max_peak_cooling: float = None):
self.borefield = copy.deepcopy(borefield)
self.load = copy.deepcopy(load)
self.depth = depth
Expand All @@ -42,6 +44,8 @@ def __init__(self, borefield: Borefield, load, depth: float, SCOP: float, SEER:
self.name = name
self.power = power
self.hourly = hourly
self.max_peak_heating = max_peak_heating
self.max_peak_cooling = max_peak_cooling

Check warning on line 48 in GHEtool/test/methods/TestMethodClass.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/test/methods/TestMethodClass.py#L47-L48

Added lines #L47 - L48 were not covered by tests

def test(self): # pragma: no cover
self.borefield.optimise_load_profile(self.load, self.depth, self.SCOP, self.SEER)
Expand Down Expand Up @@ -181,7 +185,8 @@ def optimise_load_profile_input(self) -> list:
for _, i in enumerate(self.list_of_test_objects):
if isinstance(i, SizingObject):
continue
temp.append((copy.deepcopy(i.borefield), copy.deepcopy(i.load), i.depth, i.SCOP, i.SEER, i.power, i.hourly))
temp.append((copy.deepcopy(i.borefield), copy.deepcopy(i.load), i.depth, i.SCOP, i.SEER, i.power, i.hourly,

Check warning on line 188 in GHEtool/test/methods/TestMethodClass.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/test/methods/TestMethodClass.py#L188

Added line #L188 was not covered by tests
i.max_peak_heating, i.max_peak_cooling))
return temp

@property
Expand All @@ -192,4 +197,4 @@ def optimise_load_profile_output(self) -> list:
continue
temp.append((i.percentage_heating, i.percentage_cooling, i.peak_heating_geo, i.peak_cooling_geo,
i.peak_heating_ext, i.peak_cooling_ext))
return temp
return temp

Check warning on line 200 in GHEtool/test/methods/TestMethodClass.py

View check run for this annotation

Codecov / codecov/patch

GHEtool/test/methods/TestMethodClass.py#L200

Added line #L200 was not covered by tests
Loading

0 comments on commit 5b57c27

Please sign in to comment.