Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added

- Add flow_rates as explicit argument in PressureDrop curve function.
- Add function for cascading heat pumps.
- Added _get_max_power functions to BuildingLoad classes.
- Inlet and outlet water temperature (issue #271).
- Added 'type' attribute to temperature profile plotting so also the inlet and outlet temperatures can be shown (issue
#271).
Expand Down
10 changes: 4 additions & 6 deletions GHEtool/Borefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -2012,19 +2012,17 @@ def get_rb(temperature, limit=None, power=None):
hourly_load) / self.number_of_boreholes / H)
if not self.borehole.use_constant_Rb:
results._Tf_inlet, results._Tf_outlet = self.calculate_borefield_inlet_outlet_temperature(
self.load.hourly_net_resulting_injection_power, results.peak_injection,
simulation_period=self.load.simulation_period)
hourly_load, results.peak_injection, simulation_period=self.load.simulation_period)
if sizing:
results._Tf_extraction_inlet, results._Tf_extraction_outlet = self.calculate_borefield_inlet_outlet_temperature(
self.load.hourly_net_resulting_injection_power, results._Tf_extraction,
simulation_period=self.load.simulation_period)
hourly_load, results._Tf_extraction, simulation_period=self.load.simulation_period)
return results

def calculate_difference(results_old: Union[ResultsMonthly, ResultsHourly],
result_new: Union[ResultsMonthly, ResultsHourly]) -> float:
return max(
np.max(result_new.peak_injection - results_old.peak_injection),
np.max(result_new.peak_extraction - results_old.peak_extraction))
np.max(np.abs(result_new.peak_injection - results_old.peak_injection)),
np.max(np.abs(result_new.peak_extraction - results_old.peak_extraction)))

if isinstance(self.load, _LoadDataBuilding) or \
isinstance(self.borehole.fluid_data, TemperatureDependentFluidData):
Expand Down
1 change: 1 addition & 0 deletions GHEtool/Examples/sizing_with_building_load_hourly.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def L3_sizing() -> Tuple[float, float]:
print(
f'When sizing with an L3 method, the required borehole length is {length:.2f}m. '
f'The SCOP is {borefield.load.SCOP_total:.2f}.')
borefield.load.SEER
borefield.print_temperature_profile()
return length, borefield.load.SCOP_heating

Expand Down
174 changes: 174 additions & 0 deletions GHEtool/Examples/sizing_with_building_load_hourly_limit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
"""
This document contains an example on sizing with an hourly building load and the difference between L3 and L4 sizing.
It can be seen that sizing with an hourly method not only gives a completely different result, but also that the SCOP
differs and is more accurate.
"""

from GHEtool import *
from GHEtool.VariableClasses.Efficiency._Efficiency import combine_n_heat_pumps
from typing import Tuple

# initiate ground data
data = GroundFluxTemperature(2.1, 10, flux=0.07)
borefield_gt = gt.borefield.Borefield.rectangle_field(10, 12, 6, 6, 110, 1, 0.075)

points_HP500 = np.array([
[-4.5, 84.7],
[-4.5, 66.3],
[-4.5, 38.6],
[-1.5, 93.0],
[-1.5, 72.9],
[-1.5, 42.4],
[3.5, 107.8],
[3.5, 84.6],
[3.5, 49.4],
[8.5, 123.5],
[8.5, 97.4],
[8.5, 56.9],
[11.5, 133.2],
[11.5, 105.4],
[11.5, 61.4],
])
eff_HP500 = np.array([
3.87, 4.12, 3.78,
4.12, 4.39, 4.04,
4.57, 4.89, 4.49,
5.10, 5.50, 5.08,
5.48, 5.92, 5.48,
])
points_HP400 = np.array([
[-4.5, 67.2],
[-4.5, 49.9],
[-4.5, 29.1],
[-1.5, 73.7],
[-1.5, 54.8],
[-1.5, 32.0],
[3.5, 85.2],
[3.5, 63.5],
[3.5, 37.2],
[8.5, 97.7],
[8.5, 73.1],
[8.5, 42.7],
[11.5, 105.7],
[11.5, 79.0],
[11.5, 46.0],
])
eff_HP400 = np.array([
3.91, 4.38, 3.99,
4.14, 4.64, 4.27,
4.58, 5.16, 4.77,
5.12, 5.80, 5.34,
5.51, 6.22, 5.75,
])
cascaded_system_points, cascaded_system_eff = combine_n_heat_pumps([points_HP500] * 4 + [points_HP400],
[eff_HP500] * 4 + [eff_HP400])

cop_system = COP(cascaded_system_eff, cascaded_system_points, True)


def L3_sizing() -> Tuple[float, float]:
"""
Size the borefield with a monthly sizing method.

Returns
-------
length, SCOP
"""
# initiate borefield
borefield = Borefield()

# set parameters
borefield.set_min_fluid_temperature(0)
borefield.set_max_fluid_temperature(25)

# set ground data in borefield
borefield.ground_data = data

# set Rb
borefield.Rb = 0.12

# set borefield
borefield.set_borefield(borefield_gt)

# load the hourly profile
load = HourlyBuildingLoad(efficiency_heating=cop_system)
load.load_hourly_profile(FOLDER.joinpath("Examples/hourly_profile.csv"), header=True, separator=";")
borefield.load = load

# size the borefield and plot the resulting temperature evolution
length = borefield.size(100, L3_sizing=True)
print(
f'When sizing with an L3 method (without limit), the required borehole length is {length:.2f}m. '
f'The SCOP is {borefield.load.SCOP_total:.2f}.')

# with limit
borefield.load._limit_to_max_heat_pump_power = True
length = borefield.size(100, L3_sizing=True)
borefield.print_temperature_profile()
return length


def L4_sizing() -> Tuple[float, float]:
"""
Size the borefield with an hourly sizing method.

Returns
-------
length, SCOP
"""
# initiate borefield
borefield = Borefield()

# set parameters
borefield.set_min_fluid_temperature(0)
borefield.set_max_fluid_temperature(25)

# set ground data in borefield
borefield.ground_data = data

# set Rb
borefield.Rb = 0.12

# set borefield
borefield.set_borefield(borefield_gt)

# load the hourly profile
load = HourlyBuildingLoad(efficiency_heating=cop_system)
load.load_hourly_profile(FOLDER.joinpath("Examples/hourly_profile.csv"), header=True, separator=";")
borefield.load = load

# size the borefield and plot the resulting temperature evolution
length = borefield.size(100, L4_sizing=True)
print(
f'When sizing with an L4 method, the required borehole length is {length:.2f}m. '
f'The SCOP is {borefield.load.SCOP_total:.2f}.')
borefield.load._limit_to_max_heat_pump_power = True
length = borefield.size(100, L4_sizing=True)
print(
f'When sizing with an L4 method (with limit), the required borehole length is {length:.2f}m. '
f'The SCOP is {borefield.load.SCOP_total:.2f}.')
missing_power = borefield.load.hourly_heating_load_simulation_period - borefield.load.cop._get_max_power(
borefield.results.Tf)
missing_power = np.maximum(missing_power, 0)
print(f'Over the whole simulation period, a maximum of {max(missing_power):.2f} kW cannot be delivered by the '
f'cascaded heat pumps at 0°C. This accumulates to {np.sum(missing_power):.2f} kWh over the whole simulation period.')

borefield.set_min_fluid_temperature(3)
length = borefield.size(100, L4_sizing=True)
print(
f'When sizing with an L4 method (with limit at 3°C), the required borehole length is {length:.2f}m. '
f'The SCOP is {borefield.load.SCOP_total:.2f}.')
missing_power = borefield.load.hourly_heating_load_simulation_period - borefield.load.cop._get_max_power(
borefield.results.Tf)
missing_power = np.maximum(missing_power, 0)
print(f'Over the whole simulation period, a maximum of {max(missing_power):.2f} kW cannot be delivered by the '
f'cascaded heat pumps at 0°C. This accumulates to {np.sum(missing_power):.2f} kWh over the whole simulation period.')

borefield.print_temperature_profile(plot_hourly=True)
borefield.load.SEER
return length, borefield.load.SCOP_heating


if __name__ == "__main__":
L3_sizing()
L4_sizing()
18 changes: 18 additions & 0 deletions GHEtool/Examples/variable_flow_rate.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,30 @@ def sizing():
plt.legend()
plt.ylabel('Average fluid temperature [°C]')
plt.xlabel('Time [years]')
plt.title('Borehole fluid temperature')

plt.figure()
plt.plot(time_array, rb_variable_flow, label='variable flow')
plt.plot(time_array, rb_constant_flow, label='constant flow')
plt.ylabel('Effective borehole thermal resistance [mK/W]')
plt.xlabel('Time [years]')
plt.title('Effective borehole thermal resistance')
plt.legend()

plt.figure()
plt.plot(time_array[:8760], borefield_variable_flow.results.peak_injection[:8760], label='variable flow')
plt.plot(time_array[:8760], borefield_constant_flow.results.peak_injection[:8760], label='constant flow')
plt.legend()
plt.title('Borehole fluid temperature')
plt.ylabel('Average fluid temperature [°C]')
plt.xlabel('Time [years]')

plt.figure()
plt.plot(time_array[:8760], rb_variable_flow[:8760], label='variable flow')
plt.plot(time_array[:8760], rb_constant_flow[:8760], label='constant flow')
plt.ylabel('Effective borehole thermal resistance [mK/W]')
plt.title('Effective borehole thermal resistance')
plt.xlabel('Time [years]')
plt.legend()
plt.show()

Expand Down
Loading