Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into issue107-anaconda-pac…
Browse files Browse the repository at this point in the history
…kage

# Conflicts:
#	CHANGELOG.md
  • Loading branch information
wouterpeere committed Jan 26, 2024
2 parents d99d243 + 0ac0e1c commit 92ddd68
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Added
- GHEtool is available on conda-forge (issue #107).
- Possibility to start in another month (issue #140).
- Equal functions for HourlyGeothermalLoad and MonthlyGeothermalLoadAbsolute (issue #189).
- Cylindrical borehole correction (issue #187).
- __add__ functionality for the load classes (issue #202).
Expand Down
43 changes: 43 additions & 0 deletions GHEtool/Examples/start_in_different_month.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
This example illustrates the importance of when a borefield is 'started' (i.e. when the first month of operation is).
"""

from GHEtool import *
from GHEtool.Validation.cases import load_case

import matplotlib.pyplot as plt


def start_in_different_month():
# set data
ground_data = GroundTemperatureGradient(2.5, 10)
load = MonthlyGeothermalLoadAbsolute(*load_case(1))

# create borefield object
borefield = Borefield(load=load)
borefield.ground_data = ground_data
borefield.create_rectangular_borefield(10, 8, 6, 6, 100)

borefield.set_max_avg_fluid_temperature(17)
borefield.set_min_avg_fluid_temperature(3)
borefield.calculation_setup(max_nb_of_iterations=100)

depth_list = []

# iterate over all the start months
for month in range(1, 13, 1):
borefield.load.start_month = month
depth_list.append(borefield.size_L3())

plt.figure()
plt.bar(range(1, 13, 1), depth_list)
plt.ylabel('Required depth [m]')
plt.xlabel('First month of operation')
plt.xlim(0)
plt.ylim(0)
plt.title('Required depth as a function of the first month of operation')
plt.show()


if __name__ == "__main__": # pragma: no cover
start_in_different_month()
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def hourly_heating_load(self) -> np.ndarray:
hourly heating : np.ndarray
Hourly heating values (incl. DHW) [kWh/h] for one year, so the length of the array is 8760
"""
return self._hourly_heating_load + self.dhw / 8760
return self.correct_for_start_month(self._hourly_heating_load + self.dhw / 8760)

@hourly_heating_load.setter
def hourly_heating_load(self, load: Union[np.ndarray, list, tuple]) -> None:
Expand Down Expand Up @@ -152,7 +152,7 @@ def hourly_cooling_load(self) -> np.ndarray:
hourly cooling : np.ndarray
Hourly cooling values [kWh/h] for one year, so the length of the array is 8760
"""
return self._hourly_cooling_load
return self.correct_for_start_month(self._hourly_cooling_load)

@hourly_cooling_load.setter
def hourly_cooling_load(self, load: Union[np.ndarray, list, tuple]) -> None:
Expand Down Expand Up @@ -387,3 +387,34 @@ def __add__(self, other):
return other.__add__(self)
except TypeError: # pragma: no cover
raise TypeError('Cannot perform addition. Please check if you use correct classes.') # pragma: no cover

@property
def _start_hour(self) -> int:
"""
This function returns the hour at which the year starts based on the start month.
Returns
-------
int
Start hour of the year
"""
return int(np.sum([self.UPM[i] for i in range(self.start_month - 1)]))

def correct_for_start_month(self, array: np.ndarray) -> np.ndarray:
"""
This function corrects the load for the correct start month.
If the simulation starts in september, the start month is 9 and hence the array should start
at index 9.
Parameters
----------
array : np.ndarray
Load array
Returns
-------
load : np.ndarray
"""
if self.start_month == 1:
return array
return np.concatenate((array[self._start_hour:], array[:self._start_hour]))
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ def baseload_cooling(self) -> np.ndarray:
baseload cooling : np.ndarray
Baseload cooling values [kWh/month] for one year, so the length of the array is 12
"""
return self._baseload_cooling
return self.correct_for_start_month(
self._baseload_cooling)

@baseload_cooling.setter
def baseload_cooling(self, load: Union[np.ndarray, list, tuple]) -> None:
Expand Down Expand Up @@ -157,7 +158,8 @@ def baseload_heating(self) -> np.ndarray:
baseload heating : np.ndarray
Baseload heating values (incl. DHW) [kWh/month] for one year, so the length of the array is 12
"""
return self._baseload_heating + self.dhw / 8760 * self.UPM
return self.correct_for_start_month(
self._baseload_heating + self.dhw / 8760 * self.UPM)

@baseload_heating.setter
def baseload_heating(self, load: Union[np.ndarray, list, tuple]) -> None:
Expand Down Expand Up @@ -219,7 +221,8 @@ def peak_cooling(self) -> np.ndarray:
peak cooling : np.ndarray
Peak cooling values for one year, so the length of the array is 12
"""
return np.maximum(self._peak_cooling, self.baseload_cooling_power)
return self.correct_for_start_month(
np.maximum(self._peak_cooling, self.baseload_cooling_power))

@peak_cooling.setter
def peak_cooling(self, load) -> None:
Expand Down Expand Up @@ -279,7 +282,8 @@ def peak_heating(self) -> np.ndarray:
peak heating : np.ndarray
Peak heating values for one year, so the length of the array is 12
"""
return np.maximum(np.array(self._peak_heating) + self.dhw_power, self.baseload_heating_power)
return self.correct_for_start_month(
np.maximum(np.array(self._peak_heating) + self.dhw_power, self.baseload_heating_power))

@peak_heating.setter
def peak_heating(self, load: Union[np.ndarray, list, tuple]) -> None:
Expand Down Expand Up @@ -397,3 +401,22 @@ def __add__(self, other):
return result

raise TypeError('Cannot perform addition. Please check if you use correct classes.')

def correct_for_start_month(self, array: np.ndarray) -> np.ndarray:
"""
This function corrects the load for the correct start month.
If the simulation starts in september, the start month is 9 and hence the array should start
at index 9.
Parameters
----------
array : np.ndarray
Load array
Returns
-------
load : np.ndarray
"""
if self.start_month == 1:
return array
return np.concatenate((array[self.start_month-1:], array[:self.start_month-1]))
55 changes: 55 additions & 0 deletions GHEtool/VariableClasses/LoadData/_LoadData.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,44 @@ def __init__(self, hourly_resolution: bool, simulation_period: int = DEFAULT_SIM
self.tm: int = _LoadData.AVG_UPM * 3600 # time in a month in seconds
self._all_months_equal: bool = True # true if it is assumed that all months are of the same length
self._dhw_yearly: float = 0.
self._start_month: float = 1

@property
def start_month(self) -> int:
"""
This function returns the start month.
Returns
-------
float
Start month
"""
return self._start_month

@start_month.setter
def start_month(self, month: int) -> None:
"""
This function sets the start month.
Parameters
----------
month : int
Start month (jan: 1, feb: 2 ...)
Returns
-------
None
Raises
----------
ValueError
When the start month is smaller than 1, larger than 12 or non-integer
"""

if not isinstance(month, int) or month < 1 or month > 12:
raise ValueError(f'The value for month is: {month} which is not an integer in [1,12].')

self._start_month = month

@property
def all_months_equal(self) -> bool:
Expand Down Expand Up @@ -626,3 +664,20 @@ def dhw_power(self) -> float:
dhw power : float
"""
return self._dhw_yearly / 8760

@abc.abstractmethod
def correct_for_start_month(self, array: np.ndarray) -> np.ndarray:
"""
This function corrects the load for the correct start month.
If the simulation starts in september, the start month is 9 and hence the array should start
at index 9.
Parameters
----------
array : np.ndarray
Load array
Returns
-------
load : np.ndarray
"""
1 change: 0 additions & 1 deletion GHEtool/test/methods/cases/test_BS2023.py

This file was deleted.

6 changes: 6 additions & 0 deletions GHEtool/test/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,9 @@ def test_optimise_load_profile(monkeypatch):

# optimise the load for a 10x10 field (see data above) and a fixed depth of 150m.
borefield.optimise_load_profile(load, depth=150, print_results=True)


def test_start_in_different_month(monkeypatch):
monkeypatch.setattr(plt, 'show', lambda: None)
from GHEtool.Examples.start_in_different_month import start_in_different_month
start_in_different_month()
43 changes: 43 additions & 0 deletions GHEtool/test/unit-tests/test_hourly_load_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,46 @@ def test_add_multiyear():
assert False # pragma: no cover
except TypeError:
assert True


def test_start_month_general():
load = HourlyGeothermalLoad()
assert load.start_month == 1
try:
load.start_month = 1.5
assert False # pragma: no cover
except ValueError:
assert True
try:
load.start_month = 0
assert False # pragma: no cover
except ValueError:
assert True
try:
load.start_month = 13
assert False # pragma: no cover
except ValueError:
assert True
load.start_month = 12
assert load.start_month == 12
assert load._start_hour == 11 * 730
load.start_month = 1
assert load.start_month == 1
assert load._start_hour == 0
load.start_month = 3
assert load.start_month == 3
assert load._start_hour == 730 * 2

load.all_months_equal = False
assert load._start_hour == 1416


def test_different_start_month():
load = HourlyGeothermalLoad(np.arange(1, 8761, 1), np.arange(1, 8761, 1))
load.start_month = 3
assert load.start_month == 3
assert load.hourly_cooling_load[0] == 731 * 2 - 1
assert load.hourly_heating_load[0] == 731 * 2 - 1
load.all_months_equal = False
assert load.hourly_cooling_load[0] == 1417
assert load.hourly_heating_load[0] == 1417
41 changes: 41 additions & 0 deletions GHEtool/test/unit-tests/test_monthly_load_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@ def test_checks():
assert load._check_input(np.ones(12))


def test_start_month_general():
load = MonthlyGeothermalLoadAbsolute()
assert load.start_month == 1
try:
load.start_month = 1.5
assert False # pragma: no cover
except ValueError:
assert True
try:
load.start_month = 0
assert False # pragma: no cover
except ValueError:
assert True
try:
load.start_month = 13
assert False # pragma: no cover
except ValueError:
assert True
load.start_month = 12
assert load.start_month == 12
load.start_month = 1
assert load.start_month == 1


def test_imbalance():
load = MonthlyGeothermalLoadAbsolute(np.ones(12)*10, np.ones(12), np.ones(12), np.ones(12))
assert load.imbalance == -108
Expand All @@ -33,6 +57,7 @@ def test_baseload_heating():
assert np.array_equal(load.baseload_heating_power, load.peak_heating)
try:
load.set_baseload_heating(np.ones(11))
assert False # pragma: no cover
except ValueError:
assert True

Expand All @@ -49,6 +74,7 @@ def test_baseload_cooling():

try:
load.set_baseload_cooling(np.ones(11))
assert False # pragma: no cover
except ValueError:
assert True

Expand All @@ -64,6 +90,7 @@ def test_peak_heating():
assert np.array_equal(load.peak_heating, np.array([5., 5., 5., 5., 5., 6., 7., 8., 9., 10., 11., 12.]))
try:
load.set_peak_heating(np.ones(11))
assert False # pragma: no cover
except ValueError:
assert True

Expand All @@ -79,6 +106,7 @@ def test_peak_cooling():
assert np.array_equal(load.peak_cooling, np.array([5., 5., 5., 5., 5., 6., 7., 8., 9., 10., 11., 12.]))
try:
load.set_peak_cooling(np.ones(11))
assert False # pragma: no cover
except ValueError:
assert True

Expand Down Expand Up @@ -335,3 +363,16 @@ def test_add():
load_hourly.simulation_period = 20
with pytest.warns():
result = load_1 + load_hourly


def test_different_start_month():
load = MonthlyGeothermalLoadAbsolute(baseload_heating=np.arange(1, 13, 1),
baseload_cooling=np.arange(1, 13, 1),
peak_cooling=np.arange(1, 13, 1),
peak_heating=np.arange(1, 13, 1))
load.start_month = 2
result = np.array([2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1])
assert np.array_equal(load.baseload_heating, result)
assert np.array_equal(load.baseload_cooling, result)
assert np.array_equal(load.peak_heating, result)
assert np.array_equal(load.peak_cooling, result)
Loading

0 comments on commit 92ddd68

Please sign in to comment.