Skip to content

Commit

Permalink
Merge pull request #321 from wouterpeere/issue318-account-for-tilted-…
Browse files Browse the repository at this point in the history
…boreholes

Issue318 account for tilted boreholes
  • Loading branch information
wouterpeere authored Jan 20, 2025
2 parents e5811f1 + 367efe4 commit 0863d07
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Added start_depth to the calculation of Tg in all GroundClasses (issue #137).
- Added property 'depth' to Borefield class (issue #137).
- Added function 'calculate_depth' to Borefield class (issue #137).
- Added support for titled boreholes (issue #318).

## Fixed

Expand Down
15 changes: 9 additions & 6 deletions GHEtool/Borefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import annotations

import copy
import math
import warnings
from math import pi
from typing import Tuple, Union
Expand Down Expand Up @@ -116,9 +117,6 @@ def __init__(
self.custom_gfunction: CustomGFunction = custom_gfunction
self.gfunction_calculation_object: GFunction = GFunction()

## params w.r.t. pygfunction
self.options_pygfunction: dict = {"method": "equivalent"}

# initialize variables for temperature plotting
self.results: ResultsMonthly | ResultsHourly = ResultsMonthly()

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

# initiale borehole
self.avg_tilt: float = 0.
self.borehole = Borehole()

# initiate different sizing
Expand Down Expand Up @@ -204,7 +203,7 @@ def depth(self) -> float:

def calculate_depth(self, borehole_length: float, buried_depth: float) -> float:
"""
This function calculates the depth of the borehole.
This function calculates the depth of the borehole given the average tilt of the borefield.
Parameters
----------
Expand All @@ -218,8 +217,9 @@ def calculate_depth(self, borehole_length: float, buried_depth: float) -> float:
float
Depth of the borehole [m]
"""
# TODO take into account tilt
return borehole_length + buried_depth
if np.isclose(self.avg_tilt, 0):
return borehole_length + buried_depth
return np.average([bor.H * math.cos(bor.tilt) for bor in self.borefield]) + buried_depth

@property
def H(self) -> float:
Expand Down Expand Up @@ -458,6 +458,9 @@ def borefield(self, borefield: list[gt.boreholes.Borehole] = None) -> None:
self.D = np.average([bor.D for bor in borefield])
self.r_b = np.average([bor.r_b for bor in borefield])
self._H = np.average([bor.H for bor in borefield])
self.avg_tilt = np.average([bor.tilt for bor in borefield])
if not np.isclose(self.avg_tilt, 0):
self.gfunction_calculation_object.options['method'] = 'similarities'
self.gfunction_calculation_object.remove_previous_data()
unequal_length = np.any([bor.H != borefield[0].H for bor in borefield])
if unequal_length:
Expand Down
50 changes: 50 additions & 0 deletions GHEtool/Examples/tilted_borefield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
This example shows how you can design a borefield with tilted boreholes.
"""
import math

from GHEtool import *

import matplotlib.pyplot as plt
import numpy as np
import pygfunction as gt


def tilted():
# define params
ground_data = GroundFluxTemperature(1.9, 10)
pipe_data = DoubleUTube(1.5, 0.013, 0.016, 0.4, 0.035)
fluid_data = FluidData(mfr=0.2)
fluid_data.import_fluid_from_pygfunction(gt.media.Fluid('MPG', 30, 2))
load_data = MonthlyBuildingLoadAbsolute(
np.array([.176, .174, .141, .1, .045, 0, 0, 0, 0.012, 0.065, 0.123, 0.164]) * 8 * 1350,
np.array([0, 0, 0, 0, .112, .205, .27, .264, .149, 0, 0, 0]) * 4 * 700,
np.array([1, .991, .802, .566, .264, 0, 0, 0, .0606, .368, .698, .934]) * 8,
np.array([0, 0, 0, 0, .415, .756, 1, .976, .549, 0, 0, 0]) * 4
)

# define borefield
borefield_tilted = [gt.boreholes.Borehole(150, 0.75, 0.07, -3, 0, math.pi / 7, orientation=math.pi),
gt.boreholes.Borehole(150, 0.75, 0.07, 3, 0, math.pi / 7, orientation=0)]
borefield_without_tilt = [gt.boreholes.Borehole(150, 0.75, 0.07, -3, 0),
gt.boreholes.Borehole(150, 0.75, 0.07, 3, 0)]

# initiate GHEtool object with tilted borefield
borefield = Borefield(borefield=borefield_tilted, load=load_data)
borefield.set_ground_parameters(ground_data)
borefield.set_pipe_parameters(pipe_data)
borefield.set_fluid_parameters(fluid_data)

borefield.print_temperature_profile()

# initiate GHEtool object without tilted borefield
borefield = Borefield(borefield=borefield_without_tilt, load=load_data)
borefield.set_ground_parameters(ground_data)
borefield.set_pipe_parameters(pipe_data)
borefield.set_fluid_parameters(fluid_data)

borefield.print_temperature_profile()


if __name__ == "__main__":
tilted()
7 changes: 4 additions & 3 deletions GHEtool/VariableClasses/CustomGFunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This file contains both the CustomGFunction class and all the relevant information w.r.t. custom gfunctions.
"""
import copy
import math
import pickle
import warnings
from typing import List, Union
Expand Down Expand Up @@ -225,10 +226,10 @@ def create_custom_dataset(self, borefield: List[gt.boreholes.Borehole], alpha: U

# calculate borehole buried depth
D = np.average([bor.D for bor in borefield])
# TODO correct for tilt
tilt = np.average([bor.tilt for bor in borefield])
depth = borehole_length * math.cos(tilt) + D
gfunc_uniform_T = gt.gfunction.gFunction(borefield,
alpha if isinstance(alpha, float) else alpha(borehole_length + D,
D),
alpha if isinstance(alpha, float) else alpha(depth, D),
self.time_array, options=self.options,
method=self.options["method"])

Expand Down
6 changes: 6 additions & 0 deletions GHEtool/test/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,9 @@ def test_separatus(monkeypatch):
design_with_single_U()
design_with_double_U()
design_with_separatus()


def test_tilted(monkeypatch):
monkeypatch.setattr(plt, 'show', lambda: None)
from GHEtool.Examples.tilted_borefield import tilted
tilted()
48 changes: 47 additions & 1 deletion GHEtool/test/unit-tests/test_main_class.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# noinspection PyPackageRequirements
import copy
import math

import matplotlib.pyplot as plt
import numpy as np
Expand All @@ -11,7 +12,7 @@
from GHEtool.logger import ghe_logger
from GHEtool.Validation.cases import load_case
from GHEtool.VariableClasses.LoadData import MonthlyGeothermalLoadAbsolute, HourlyGeothermalLoad, HourlyBuildingLoad, \
HourlyBuildingLoadMultiYear
HourlyBuildingLoadMultiYear, MonthlyBuildingLoadAbsolute
from GHEtool.VariableClasses.BaseClass import UnsolvableDueToTemperatureGradient

data = GroundConstantTemperature(3, 10)
Expand Down Expand Up @@ -70,6 +71,7 @@ def test_nb_of_boreholes():
borefield.set_ground_parameters(data_ground_flux)
assert borefield.number_of_boreholes == 120
borefield.set_borefield(gt.boreholes.rectangle_field(5, 5, 6, 6, 110, 0.1, 0.07))
assert np.isclose(borefield.avg_tilt, 0)
assert np.isclose(borefield.H, 110)
assert np.isclose(borefield.r_b, 0.07)
assert np.isclose(borefield.D, 0.1)
Expand All @@ -78,11 +80,13 @@ def test_nb_of_boreholes():
assert np.any(borefield.gfunction_calculation_object.borehole_length_array)
borefield.borefield = gt.boreholes.rectangle_field(6, 5, 6, 6, 100, 1, 0.075)
assert not np.any(borefield.gfunction_calculation_object.borehole_length_array)
assert np.isclose(borefield.avg_tilt, 0)
assert np.isclose(borefield.H, 100)
assert np.isclose(borefield.r_b, 0.075)
assert np.isclose(borefield.D, 1)
borefield.gfunction(5000, 110)
assert np.any(borefield.gfunction_calculation_object.borehole_length_array)
assert np.isclose(borefield.avg_tilt, 0)
assert borefield.number_of_boreholes == 30
borefield.borefield = None
assert not np.any(borefield.gfunction_calculation_object.borehole_length_array)
Expand All @@ -91,6 +95,7 @@ def test_nb_of_boreholes():
borefield.borefield = gt.boreholes.rectangle_field(6, 5, 6, 6, 100, 1, 0.075)
borefield.gfunction(5000, 110)
assert np.any(borefield.gfunction_calculation_object.borehole_length_array)
assert np.isclose(borefield.avg_tilt, 0)
borefield.set_borefield(None)
assert not np.any(borefield.gfunction_calculation_object.borehole_length_array)
assert borefield.number_of_boreholes == 0
Expand All @@ -105,6 +110,17 @@ def test_set_borefield():
assert borefield.H == 125


def test_tilt():
borefield = Borefield()
borefield.set_borefield([
gt.boreholes.Borehole(100, 4, 0.075, 0, 0),
gt.boreholes.Borehole(150, 4, 0.075, 10, 0, tilt=math.pi / 9)
])
assert borefield.H == 125
assert np.isclose(borefield.avg_tilt, math.pi / 18)
assert np.isclose(borefield.depth, 4 + (100 + 150 * math.cos(math.pi / 9)) / 2)


def test_gfunction_with_irregular_borehole_depth():
borefield = Borefield()
borefield.ground_data = ground_data_constant
Expand Down Expand Up @@ -1166,3 +1182,33 @@ def test_repr_():
'Peak extraction duration [hour]: 6.0\n' \
'Simulation period [year]: 20\n' \
'First month of simulation [-]: 1' == borefield.__repr__()


def test_with_titled_borefield():
# define params
ground_data = GroundFluxTemperature(1.9, 10)
pipe_data = DoubleUTube(1.5, 0.013, 0.016, 0.4, 0.035)
fluid_data = FluidData(mfr=0.2)
fluid_data.import_fluid_from_pygfunction(gt.media.Fluid('MPG', 30, 2))
load_data = MonthlyBuildingLoadAbsolute(
np.array([.176, .174, .141, .1, .045, 0, 0, 0, 0.012, 0.065, 0.123, 0.164]) * 8 * 1350,
np.array([0, 0, 0, 0, .112, .205, .27, .264, .149, 0, 0, 0]) * 4 * 700,
np.array([1, .991, .802, .566, .264, 0, 0, 0, .0606, .368, .698, .934]) * 8,
np.array([0, 0, 0, 0, .415, .756, 1, .976, .549, 0, 0, 0]) * 4
)

# define borefield
borefield_tilted = [gt.boreholes.Borehole(150, 0.75, 0.07, -3, 0, math.pi / 7, orientation=math.pi),
gt.boreholes.Borehole(150, 0.75, 0.07, 3, 0, math.pi / 7, orientation=0)]

# initiate GHEtool object with tilted borefield
borefield = Borefield(borefield=borefield_tilted, load=load_data)
borefield.set_ground_parameters(ground_data)
borefield.set_pipe_parameters(pipe_data)
borefield.set_fluid_parameters(fluid_data)
borefield.set_max_avg_fluid_temperature(17)

assert np.isclose(borefield.depth, 150 * math.cos(math.pi / 7) + 0.75)
assert np.isclose(borefield.ground_data.calculate_Tg(borefield.depth, borefield.D), 12.157557845032045)

assert np.isclose(borefield.size_L3(), 111.58488656187147)
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = GHEtool
version = 2.3.1.dev1
version = 2.3.1.dev2
author = Wouter Peere
author_email = [email protected]
description = Python package for borefield sizing
Expand Down

0 comments on commit 0863d07

Please sign in to comment.