Skip to content

Commit 0863d07

Browse files
authored
Merge pull request #321 from wouterpeere/issue318-account-for-tilted-boreholes
Issue318 account for tilted boreholes
2 parents e5811f1 + 367efe4 commit 0863d07

File tree

7 files changed

+118
-11
lines changed

7 files changed

+118
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1515
- Added start_depth to the calculation of Tg in all GroundClasses (issue #137).
1616
- Added property 'depth' to Borefield class (issue #137).
1717
- Added function 'calculate_depth' to Borefield class (issue #137).
18+
- Added support for titled boreholes (issue #318).
1819

1920
## Fixed
2021

GHEtool/Borefield.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from __future__ import annotations
55

66
import copy
7+
import math
78
import warnings
89
from math import pi
910
from typing import Tuple, Union
@@ -116,9 +117,6 @@ def __init__(
116117
self.custom_gfunction: CustomGFunction = custom_gfunction
117118
self.gfunction_calculation_object: GFunction = GFunction()
118119

119-
## params w.r.t. pygfunction
120-
self.options_pygfunction: dict = {"method": "equivalent"}
121-
122120
# initialize variables for temperature plotting
123121
self.results: ResultsMonthly | ResultsHourly = ResultsMonthly()
124122

@@ -133,6 +131,7 @@ def __init__(
133131
self.Tf_min: float = 0.0 # minimum temperature of the fluid
134132

135133
# initiale borehole
134+
self.avg_tilt: float = 0.
136135
self.borehole = Borehole()
137136

138137
# initiate different sizing
@@ -204,7 +203,7 @@ def depth(self) -> float:
204203

205204
def calculate_depth(self, borehole_length: float, buried_depth: float) -> float:
206205
"""
207-
This function calculates the depth of the borehole.
206+
This function calculates the depth of the borehole given the average tilt of the borefield.
208207
209208
Parameters
210209
----------
@@ -218,8 +217,9 @@ def calculate_depth(self, borehole_length: float, buried_depth: float) -> float:
218217
float
219218
Depth of the borehole [m]
220219
"""
221-
# TODO take into account tilt
222-
return borehole_length + buried_depth
220+
if np.isclose(self.avg_tilt, 0):
221+
return borehole_length + buried_depth
222+
return np.average([bor.H * math.cos(bor.tilt) for bor in self.borefield]) + buried_depth
223223

224224
@property
225225
def H(self) -> float:
@@ -458,6 +458,9 @@ def borefield(self, borefield: list[gt.boreholes.Borehole] = None) -> None:
458458
self.D = np.average([bor.D for bor in borefield])
459459
self.r_b = np.average([bor.r_b for bor in borefield])
460460
self._H = np.average([bor.H for bor in borefield])
461+
self.avg_tilt = np.average([bor.tilt for bor in borefield])
462+
if not np.isclose(self.avg_tilt, 0):
463+
self.gfunction_calculation_object.options['method'] = 'similarities'
461464
self.gfunction_calculation_object.remove_previous_data()
462465
unequal_length = np.any([bor.H != borefield[0].H for bor in borefield])
463466
if unequal_length:
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""
2+
This example shows how you can design a borefield with tilted boreholes.
3+
"""
4+
import math
5+
6+
from GHEtool import *
7+
8+
import matplotlib.pyplot as plt
9+
import numpy as np
10+
import pygfunction as gt
11+
12+
13+
def tilted():
14+
# define params
15+
ground_data = GroundFluxTemperature(1.9, 10)
16+
pipe_data = DoubleUTube(1.5, 0.013, 0.016, 0.4, 0.035)
17+
fluid_data = FluidData(mfr=0.2)
18+
fluid_data.import_fluid_from_pygfunction(gt.media.Fluid('MPG', 30, 2))
19+
load_data = MonthlyBuildingLoadAbsolute(
20+
np.array([.176, .174, .141, .1, .045, 0, 0, 0, 0.012, 0.065, 0.123, 0.164]) * 8 * 1350,
21+
np.array([0, 0, 0, 0, .112, .205, .27, .264, .149, 0, 0, 0]) * 4 * 700,
22+
np.array([1, .991, .802, .566, .264, 0, 0, 0, .0606, .368, .698, .934]) * 8,
23+
np.array([0, 0, 0, 0, .415, .756, 1, .976, .549, 0, 0, 0]) * 4
24+
)
25+
26+
# define borefield
27+
borefield_tilted = [gt.boreholes.Borehole(150, 0.75, 0.07, -3, 0, math.pi / 7, orientation=math.pi),
28+
gt.boreholes.Borehole(150, 0.75, 0.07, 3, 0, math.pi / 7, orientation=0)]
29+
borefield_without_tilt = [gt.boreholes.Borehole(150, 0.75, 0.07, -3, 0),
30+
gt.boreholes.Borehole(150, 0.75, 0.07, 3, 0)]
31+
32+
# initiate GHEtool object with tilted borefield
33+
borefield = Borefield(borefield=borefield_tilted, load=load_data)
34+
borefield.set_ground_parameters(ground_data)
35+
borefield.set_pipe_parameters(pipe_data)
36+
borefield.set_fluid_parameters(fluid_data)
37+
38+
borefield.print_temperature_profile()
39+
40+
# initiate GHEtool object without tilted borefield
41+
borefield = Borefield(borefield=borefield_without_tilt, load=load_data)
42+
borefield.set_ground_parameters(ground_data)
43+
borefield.set_pipe_parameters(pipe_data)
44+
borefield.set_fluid_parameters(fluid_data)
45+
46+
borefield.print_temperature_profile()
47+
48+
49+
if __name__ == "__main__":
50+
tilted()

GHEtool/VariableClasses/CustomGFunction.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
This file contains both the CustomGFunction class and all the relevant information w.r.t. custom gfunctions.
33
"""
44
import copy
5+
import math
56
import pickle
67
import warnings
78
from typing import List, Union
@@ -225,10 +226,10 @@ def create_custom_dataset(self, borefield: List[gt.boreholes.Borehole], alpha: U
225226

226227
# calculate borehole buried depth
227228
D = np.average([bor.D for bor in borefield])
228-
# TODO correct for tilt
229+
tilt = np.average([bor.tilt for bor in borefield])
230+
depth = borehole_length * math.cos(tilt) + D
229231
gfunc_uniform_T = gt.gfunction.gFunction(borefield,
230-
alpha if isinstance(alpha, float) else alpha(borehole_length + D,
231-
D),
232+
alpha if isinstance(alpha, float) else alpha(depth, D),
232233
self.time_array, options=self.options,
233234
method=self.options["method"])
234235

GHEtool/test/test_examples.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,9 @@ def test_separatus(monkeypatch):
7979
design_with_single_U()
8080
design_with_double_U()
8181
design_with_separatus()
82+
83+
84+
def test_tilted(monkeypatch):
85+
monkeypatch.setattr(plt, 'show', lambda: None)
86+
from GHEtool.Examples.tilted_borefield import tilted
87+
tilted()

GHEtool/test/unit-tests/test_main_class.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# noinspection PyPackageRequirements
22
import copy
3+
import math
34

45
import matplotlib.pyplot as plt
56
import numpy as np
@@ -11,7 +12,7 @@
1112
from GHEtool.logger import ghe_logger
1213
from GHEtool.Validation.cases import load_case
1314
from GHEtool.VariableClasses.LoadData import MonthlyGeothermalLoadAbsolute, HourlyGeothermalLoad, HourlyBuildingLoad, \
14-
HourlyBuildingLoadMultiYear
15+
HourlyBuildingLoadMultiYear, MonthlyBuildingLoadAbsolute
1516
from GHEtool.VariableClasses.BaseClass import UnsolvableDueToTemperatureGradient
1617

1718
data = GroundConstantTemperature(3, 10)
@@ -70,6 +71,7 @@ def test_nb_of_boreholes():
7071
borefield.set_ground_parameters(data_ground_flux)
7172
assert borefield.number_of_boreholes == 120
7273
borefield.set_borefield(gt.boreholes.rectangle_field(5, 5, 6, 6, 110, 0.1, 0.07))
74+
assert np.isclose(borefield.avg_tilt, 0)
7375
assert np.isclose(borefield.H, 110)
7476
assert np.isclose(borefield.r_b, 0.07)
7577
assert np.isclose(borefield.D, 0.1)
@@ -78,11 +80,13 @@ def test_nb_of_boreholes():
7880
assert np.any(borefield.gfunction_calculation_object.borehole_length_array)
7981
borefield.borefield = gt.boreholes.rectangle_field(6, 5, 6, 6, 100, 1, 0.075)
8082
assert not np.any(borefield.gfunction_calculation_object.borehole_length_array)
83+
assert np.isclose(borefield.avg_tilt, 0)
8184
assert np.isclose(borefield.H, 100)
8285
assert np.isclose(borefield.r_b, 0.075)
8386
assert np.isclose(borefield.D, 1)
8487
borefield.gfunction(5000, 110)
8588
assert np.any(borefield.gfunction_calculation_object.borehole_length_array)
89+
assert np.isclose(borefield.avg_tilt, 0)
8690
assert borefield.number_of_boreholes == 30
8791
borefield.borefield = None
8892
assert not np.any(borefield.gfunction_calculation_object.borehole_length_array)
@@ -91,6 +95,7 @@ def test_nb_of_boreholes():
9195
borefield.borefield = gt.boreholes.rectangle_field(6, 5, 6, 6, 100, 1, 0.075)
9296
borefield.gfunction(5000, 110)
9397
assert np.any(borefield.gfunction_calculation_object.borehole_length_array)
98+
assert np.isclose(borefield.avg_tilt, 0)
9499
borefield.set_borefield(None)
95100
assert not np.any(borefield.gfunction_calculation_object.borehole_length_array)
96101
assert borefield.number_of_boreholes == 0
@@ -105,6 +110,17 @@ def test_set_borefield():
105110
assert borefield.H == 125
106111

107112

113+
def test_tilt():
114+
borefield = Borefield()
115+
borefield.set_borefield([
116+
gt.boreholes.Borehole(100, 4, 0.075, 0, 0),
117+
gt.boreholes.Borehole(150, 4, 0.075, 10, 0, tilt=math.pi / 9)
118+
])
119+
assert borefield.H == 125
120+
assert np.isclose(borefield.avg_tilt, math.pi / 18)
121+
assert np.isclose(borefield.depth, 4 + (100 + 150 * math.cos(math.pi / 9)) / 2)
122+
123+
108124
def test_gfunction_with_irregular_borehole_depth():
109125
borefield = Borefield()
110126
borefield.ground_data = ground_data_constant
@@ -1166,3 +1182,33 @@ def test_repr_():
11661182
'Peak extraction duration [hour]: 6.0\n' \
11671183
'Simulation period [year]: 20\n' \
11681184
'First month of simulation [-]: 1' == borefield.__repr__()
1185+
1186+
1187+
def test_with_titled_borefield():
1188+
# define params
1189+
ground_data = GroundFluxTemperature(1.9, 10)
1190+
pipe_data = DoubleUTube(1.5, 0.013, 0.016, 0.4, 0.035)
1191+
fluid_data = FluidData(mfr=0.2)
1192+
fluid_data.import_fluid_from_pygfunction(gt.media.Fluid('MPG', 30, 2))
1193+
load_data = MonthlyBuildingLoadAbsolute(
1194+
np.array([.176, .174, .141, .1, .045, 0, 0, 0, 0.012, 0.065, 0.123, 0.164]) * 8 * 1350,
1195+
np.array([0, 0, 0, 0, .112, .205, .27, .264, .149, 0, 0, 0]) * 4 * 700,
1196+
np.array([1, .991, .802, .566, .264, 0, 0, 0, .0606, .368, .698, .934]) * 8,
1197+
np.array([0, 0, 0, 0, .415, .756, 1, .976, .549, 0, 0, 0]) * 4
1198+
)
1199+
1200+
# define borefield
1201+
borefield_tilted = [gt.boreholes.Borehole(150, 0.75, 0.07, -3, 0, math.pi / 7, orientation=math.pi),
1202+
gt.boreholes.Borehole(150, 0.75, 0.07, 3, 0, math.pi / 7, orientation=0)]
1203+
1204+
# initiate GHEtool object with tilted borefield
1205+
borefield = Borefield(borefield=borefield_tilted, load=load_data)
1206+
borefield.set_ground_parameters(ground_data)
1207+
borefield.set_pipe_parameters(pipe_data)
1208+
borefield.set_fluid_parameters(fluid_data)
1209+
borefield.set_max_avg_fluid_temperature(17)
1210+
1211+
assert np.isclose(borefield.depth, 150 * math.cos(math.pi / 7) + 0.75)
1212+
assert np.isclose(borefield.ground_data.calculate_Tg(borefield.depth, borefield.D), 12.157557845032045)
1213+
1214+
assert np.isclose(borefield.size_L3(), 111.58488656187147)

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = GHEtool
3-
version = 2.3.1.dev1
3+
version = 2.3.1.dev2
44
author = Wouter Peere
55
author_email = wouter@ghetool.eu
66
description = Python package for borefield sizing

0 commit comments

Comments
 (0)