Main class

This file contains all the code for the borefield calculations.

class GHEtool.main_class.Borefield(peak_heating: Optional[Union[ndarray, list]] = None, peak_cooling: Optional[Union[ndarray, list]] = None, baseload_heating: Optional[Union[ndarray, list]] = None, baseload_cooling: Optional[Union[ndarray, list]] = None, borefield=None, custom_gfunction: Optional[CustomGFunction] = None, load: Optional[_LoadData] = None)

Bases: BaseClass

Main borefield class

Parameters
peak_heatinglist, numpy array

Monthly peak heating values [kW]

peak_coolinglist, numpy array

Monthly peak cooling values [kW]

baseload_heatinglist, numpy array

Monthly baseload heating values [kWh]

baseload_coolinglist, numpy array

Monthly baseload heating values [kWh]

borefieldpygfunction borehole/borefield object

Set the borefield for which the calculations will be carried out

custom_gfunctionCustomGFunction

Custom gfunction dataset

Examples

monthly peak values [kW]

>>> peak_cooling = np.array([0., 0, 34., 69., 133., 187., 213., 240., 160., 37., 0., 0.])
>>> peak_heating = np.array([160., 142, 102., 55., 0., 0., 0., 0., 40.4, 85., 119., 136.])

annual heating and cooling load [kWh]

>>> annual_heating_load = 300 * 10 ** 3
>>> annual_cooling_load = 160 * 10 ** 3

percentage of annual load per month (15.5% for January …)

>>> monthly_load_heating_percentage = np.array([0.155, 0.148, 0.125, .099, .064, 0., 0., 0., 0.061, 0.087, 0.117, 0.144])
>>> monthly_load_cooling_percentage = np.array([0.025, 0.05, 0.05, .05, .075, .1, .2, .2, .1, .075, .05, .025])

resulting load per month [kWh]

>>> monthly_load_heating = annual_heating_load * monthly_load_heating_percentage
>>> monthly_load_cooling = annual_cooling_load * monthly_load_cooling_percentage

create the borefield object

>>> borefield = Borefield()

set the load

>>> load = MonthlyGeothermalLoadAbsolute(monthly_load_heating, monthly_load_cooling, peak_heating, peak_cooling)
>>> borefield.load = load
property Rb: float

This function returns the equivalent borehole thermal resistance.

Returns
Rbfloat

Equivalent borehole thermal resistance [mK/W]

property Re: float

Reynolds number.

Returns
float

Reynolds number

static activate_logger() None

This function activates the logging.

Returns
None
property borefield

Returns the hidden _borefield variable.

Returns
Hidden _borefield object
calculate_next_depth_deep_sizing(current_depth: float) float

This method is a slower but more robust way of calculating the next depth in the sizing iteration when the borefield is sized for the maximum fluid temperature when there is a non-constant ground temperature. The method is based (as can be seen in its corresponding validation document) on the assumption that the difference between the maximum temperature in peak cooling and the average undisturbed ground temperature is irreversily proportional to the depth. In this way, given this difference in temperature and the current depth, a new depth can be calculated.

Parameters
current_depthfloat

The current depth of the borefield [m]

Returns
float

New depth of the borefield [m]

calculate_quadrant() int

This function returns the borefield quadrant (as defined by Peere et al., 2021 1) based on the calculated temperature profile. If there is no limiting quadrant, None is returned.

Quadrant 1 is limited in the first year by the maximum temperature

Quadrant 2 is limited in the last year by the maximum temperature

Quadrant 3 is limited in the first year by the minimum temperature

Quadrant 4 is limited in the last year by the maximum temperature

Returns
quadrantint

The quadrant which limits the borefield

References

1

Peere, W., Picard, D., Cupeiro Figueroa, I., Boydens, W., and Helsen, L. (2021) Validated combined first and last year borefield sizing methodology. In Proceedings of International Building Simulation Conference 2021. Brugge (Belgium), 1-3 September 2021. https://doi.org/10.26868/25222708.2021.30180

calculate_temperatures(depth: Optional[float] = None, hourly: bool = False) None

Calculate all the temperatures without plotting the figure. When depth is given, it calculates it for a given depth.

Parameters
depthfloat

Depth for which the temperature profile should be calculated for [m]

hourlybool

True when the temperatures should be calculated based on hourly data

Returns
None
calculation_setup(calculation_setup: Optional[CalculationSetup] = None, use_constant_Rb: Optional[bool] = None, **kwargs) None

This function sets the options for the sizing function.

  • The L2 sizing is the one explained in (Peere et al., 2021) 2 and is the quickest method (it uses 3 pulses)

  • The L3 sizing is a more general approach which is slower but more accurate (it uses 24 pulses/year)

  • The L4 sizing is the most exact one, since it uses hourly data (8760 pulses/year)

Parameters
calculation_setupCalculationSetup

An instance of the CalculationSetup class. When this argument differs from None, all the other parameters are set based on this calculation_setup

use_constant_Rbbool

True if a constant borehole equivalent resistance (Rb*) value should be used

kwargs

Dictionary with all the other options that can be set within GHEtool. For a complete list, see the documentation in the CalculationSetup class.

Returns
None

References

2(1,2,3,4)

Peere, W., Picard, D., Cupeiro Figueroa, I., Boydens, W., and Helsen, L. (2021) Validated combined first and last year borefield sizing methodology. In Proceedings of International Building Simulation Conference 2021. Brugge (Belgium), 1-3 September 2021. https://doi.org/10.26868/25222708.2021.30180

3

Peere, W. (2020) Methode voor economische optimalisatie van geothermische verwarmings- en koelsystemen. Master thesis, Department of Mechanical Engineering, KU Leuven, Belgium.

create_circular_borefield(N: int, R: float, H: float, D: float = 1, r_b: float = 0.075)

This function creates a circular borefield. It calls the pygfunction module in the background. The documentation of this function is based on pygfunction.

Parameters
Nint

Number of boreholes in the borefield

Rfloat

Distance of boreholes from the center of the field

Hfloat

Borehole depth [m]

Dfloat

Borehole buried depth [m]

r_bfloat

Borehole radius [m]

Returns
pygfunction borefield object
create_custom_dataset(time_array: Optional[Union[ndarray, list]] = None, depth_array: Optional[Union[ndarray, list]] = None, options: dict = {}) None

This function makes a datafile for a given custom borefield and sets it for the borefield object. It automatically sets this datafile in the current borefield object so it can be used as a source for the interpolation of g-values.

Parameters
time_arraylist, np.array

Time values (in seconds) used for the calculation of the datafile

depth_arraylist, np.array

List or arrays of depths for which the datafile should be created

optionsdict

Options for the g-function calculation (check pygfunction.gfunction.gFunction() for more information)

Returns
None
Raises
ValueError

When no borefield or ground data is set

create_rectangular_borefield(N_1: int, N_2: int, B_1: int, B_2: int, H: float, D: float = 1, r_b: float = 0.075)

This function creates a rectangular borefield. It calls the pygfunction module in the background. The documentation of this function is based on pygfunction.

Parameters
N_1int

Number of boreholes in the x direction

N_2int

Number of boreholes in the y direction

B_1int

Distance between adjacent boreholes in the x direction [m]

B_2int

Distance between adjacent boreholes in the y direction [m]

Hfloat

Borehole depth [m]

Dfloat

Borehole buried depth [m]

r_bfloat

Borehole radius [m]

Returns
pygfunction borefield object
static deactivate_logger() None

This function deactivates the logging.

Returns
None
gfunction(time_value: list | float | numpy.ndarray, H: Optional[float] = None) ndarray

This function returns the gfunction value. It can do so by either calculating the gfunctions just-in-time or by interpolating from a loaded custom data file.

Parameters
time_valuelist, float, np.ndarray

Time value(s) in seconds at which the gfunctions should be calculated

Hfloat

Depth [m] at which the gfunctions should be calculated. If no depth is given, the current depth is taken.

Returns
gvaluenp.ndarray

1D array with the g-values for all the requested time_value(s)

property ground_data: _GroundData

” This function returns the ground data.

Returns
ground dataGroundData
property investment_cost: float

This function calculates the investment cost based on a cost profile linear to the total borehole length.

Returns
float

Investment cost

property load: GHEtool.VariableClasses.LoadData._LoadData._LoadData | GHEtool.VariableClasses.LoadData.GeothermalLoad.HourlyGeothermalLoad.HourlyGeothermalLoad | GHEtool.VariableClasses.LoadData.GeothermalLoad.MonthlyGeothermalLoadAbsolute.MonthlyGeothermalLoadAbsolute

This returns the LoadData object.

Returns
Load data: LoadData
load_custom_gfunction(location: str) None

This function loads the custom gfunction.

Parameters
locationstr

Path to the location of the custom gfunction file

Returns
None
optimise_load_profile(building_load: HourlyGeothermalLoad, depth: Optional[float] = None, SCOP: float = 1000000, SEER: float = 1000000, print_results: bool = False, temperature_threshold: float = 0.05) None

This function optimises the load based on the given borefield and the given hourly load. (When the load is not geothermal, the SCOP and SEER are used to convert it to a geothermal load.) It does so based on a load-duration curve. The temperatures of the borefield are calculated on a monthly basis, even though we have hourly data, for an hourly calculation of the temperatures would take a very long time.

Parameters
building_load_LoadData

Load data used for the optimisation

depthfloat

Depth of the boreholes in the borefield [m]

SCOPfloat

SCOP of the geothermal system (needed to convert hourly building load to geothermal load)

SEERfloat

SEER of the geothermal system (needed to convert hourly building load to geothermal load)

print_resultsbool

True when the results of this optimisation are to be printed in the terminal

temperature_thresholdfloat

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.

Returns
None
Raises
ValueError

ValueError if no hourly load is given or the threshold is negative

plot_load_duration(legend: bool = False) Tuple[Figure, Axes]

This function makes a load-duration curve from the hourly values.

Parameters
legendbool

True if the figure should have a legend

Returns
Tuple

plt.Figure, plt.Axes

print_temperature_profile(legend: bool = True, plot_hourly: bool = False) None

This function plots the temperature profile for the calculated depth. It uses the available temperature profile data.

Parameters
legendbool

True if the legend should be printed

plot_hourlybool

True if the temperature profile printed should be based on the hourly load profile.

Returns
fig, ax

Figure object

print_temperature_profile_fixed_depth(depth: float, legend: bool = True, plot_hourly: bool = False)

This function plots the temperature profile for a fixed depth. It uses the already calculated temperature profile data, if available.

Parameters
depthfloat

Depth at which the temperature profile should be shown

legendbool

True if the legend should be printed

plot_hourlybool

True if the temperature profile printed should be based on the hourly load profile.

Returns
fig, ax

Figure object

set_Rb(Rb: float) None

This function sets the constant equivalent borehole thermal resistance.

Parameters
Rbfloat

Equivalent borehole thermal resistance (mK/W)

Returns
None
set_borefield(borefield: Optional[list[pygfunction.boreholes.Borehole]] = None) None

This function set the borefield object. When None is given, the borefield will be deleted.

Parameters
borefieldList[pygfunction.boreholes.Borehole]

Borefield created with the pygfunction package

Returns
None
set_fluid_parameters(data: FluidData) None

This function sets the fluid parameters.

Parameters
dataFluidData

All the relevant fluid data

Returns
None
set_ground_parameters(data: _GroundData) None

This function sets the relevant ground parameters.

Parameters
dataGroundData

All the relevant ground data

Returns
None
set_investment_cost(investment_cost: Optional[list] = None) None

This function sets the investment cost. This is linear with respect to the total field length. If None, the default is set.

Parameters
investment_costlist

1D array of polynomial coefficients (including coefficients equal to zero) from highest degree to the constant term

Returns
None
set_length_peak(length: float = 6) None

This function sets the length of the peak.

Parameters
lengthfloat

Length of the peak [hours]

Returns
None
set_load(load: _LoadData) None

This function sets the _load attribute.

Parameters
load_LoadData

Load data object

Returns
None
set_max_avg_fluid_temperature(temp: float) None

This functions sets the maximal average fluid temperature to temp.

Parameters
tempfloat

Maximal average fluid temperature [deg C]

Returns
None
Raises
ValueError

When the maximal average fluid temperature is lower than the minimal average fluid temperature

set_min_avg_fluid_temperature(temp: float) None

This functions sets the minimal average fluid temperature to temp.

Parameters
tempfloat

Minimal average fluid temperature [deg C]

Returns
None
Raises
ValueError

When the maximal average temperature is lower than the minimal average temperature

set_options_gfunction_calculation(options: dict) None

This function sets the options for the gfunction calculation of pygfunction. This dictionary is directly passed through to the gFunction class of pygfunction. For more information, please visit the documentation of pygfunction.

Parameters
optionsdict

Dictionary with options for the gFunction class of pygfunction

Returns
None
set_pipe_parameters(data: _PipeData) None

This function sets the pipe parameters.

Parameters
dataPipeData

All the relevant pipe parameters

Returns
None
property simulation_period: int

This returns the simulation period from the LoadData object.

Returns
Simulation period [years]int
size(H_init: Optional[float] = None, use_constant_Rb: Optional[bool] = None, L2_sizing: Optional[bool] = None, L3_sizing: Optional[bool] = None, L4_sizing: Optional[bool] = None, quadrant_sizing: Optional[int] = None, **kwargs) float

This function sets the options for the sizing function.

  • The L2 sizing is the one explained in (Peere et al., 2021) 2 and is the quickest method (it uses 3 pulses)

  • The L3 sizing is a more general approach which is slower but more accurate (it uses 24 pulses/year)

  • The L4 sizing is the most exact one, since it uses hourly data (8760 pulses/year)

Please note that the changes sizing setup changes here are not saved! Use self.setupSizing for this.

Parameters
H_initfloat

Initial depth for the iteration. If None, the default H_init is chosen.

use_constant_Rbbool

True if a constant borehole equivalent resistance (Rb*) value should be used

L2_sizingbool

True if a sizing with the L2 method is needed

L3_sizingbool

True if a sizing with the L3 method is needed

L4_sizingbool

True if a sizing with the L4 method is needed

quadrant_sizingint

Differs from 0 when a sizing in a certain quadrant is desired. Quadrants are developed by (Peere et al., 2021) 2, 3

kwargsdict

Dictionary with all the other options that can be set within GHEtool. For a complete list, see the documentation in the CalculationSetup class.

Returns
borehole depthfloat
Raises
ValueError

ValueError when no ground data is provided

size_L2(H_init: Optional[float] = None, quadrant_sizing: int = 0) float

This function sizes the of the given configuration according to the methodology explained in (Peere et al., 2021) 2, which is a L2 method. When quadrant sizing is other than 0, it sizes the field based on the asked quadrant. It returns the borefield depth.

Parameters
H_initfloat

Initial depth from where to start the iteration [m]

quadrant_sizingint

If a quadrant is given the sizing is performed for this quadrant else for the relevant

Returns
Hfloat

Required depth of the borefield [m]

Raises
ValueError

ValueError when no ground data is provided or quadrant is not in range.

size_L3(H_init: Optional[float] = None, quadrant_sizing: int = 0) float

This function sizes the borefield based on a monthly (L3) method.

Parameters
H_initfloat

Initial depth from where to start the iteration [m]

quadrant_sizingint

If a quadrant is given the sizing is performed for this quadrant else for the relevant

Returns
Hfloat

Required depth of the borefield [m]

Raises
ValueError

ValueError when no ground data is provided or quadrant is not in range.

UnsolvableDueToTemperatureGradient

Error when the field cannot be sized.

size_L4(H_init: Optional[float] = None, quadrant_sizing: int = 0) float

This function sizes the borefield based on an hourly (L4) sizing methodology.

Parameters
H_initfloat

Initial depth from where to start the iteration [m]

quadrant_sizingint

If a quadrant is given the sizing is performed for this quadrant else for the relevant

Returns
Hfloat

Required depth of the borefield [m]

Raises
ValueError

ValueError when no ground data is provided or quadrant is not in range.

UnsolvableDueToTemperatureGradient

When the field cannot be sized due to the temperature gradient.