Sizing with equivalent borehole resistance calculation

  1"""
  2This document compares the sizing with a constant Rb*-value with sizing where the Rb*-value is being recalculated.
  3For the test, the L2 sizing method is used.
  4The comparison is based on speed and relative accuracy in the result.
  5It is shown that the speed difference is significant, but so is the difference in the result. With a constant Rb* value, it is important that the initial depth is rather accurate.
  6"""
  7
  8import time
  9
 10import numpy as np
 11import pygfunction as gt
 12
 13from GHEtool import Borefield, FluidData, GroundConstantTemperature, DoubleUTube, MonthlyGeothermalLoadAbsolute
 14
 15
 16def sizing_with_Rb():
 17    number_of_iterations = 50
 18    max_value_cooling = 700
 19    max_value_heating = 800
 20
 21    # initiate the arrays
 22    results_Rb_static = np.empty(number_of_iterations)
 23    results_Rb_dynamic = np.empty(number_of_iterations)
 24    difference_results = np.empty(number_of_iterations)
 25
 26    monthly_load_cooling_array = np.empty((number_of_iterations, 12))
 27    monthly_load_heating_array = np.empty((number_of_iterations, 12))
 28    peak_load_cooling_array = np.empty((number_of_iterations, 12))
 29    peak_load_heating_array = np.empty((number_of_iterations, 12))
 30
 31    # populate arrays with random values
 32    for i in range(number_of_iterations):
 33        for j in range(12):
 34            monthly_load_cooling_array[i, j] = np.random.randint(0, max_value_cooling)
 35            monthly_load_heating_array[i, j] = np.random.randint(0, max_value_heating)
 36            peak_load_cooling_array[i, j] = np.random.randint(monthly_load_cooling_array[i, j], max_value_cooling)
 37            peak_load_heating_array[i, j] = np.random.randint(monthly_load_heating_array[i, j], max_value_heating)
 38
 39    # initiate borefield model
 40    data = GroundConstantTemperature(3, 10)  # ground data with an inaccurate guess of 100m for the depth of the borefield
 41    fluid_data = FluidData(0.2, 0.568, 998, 4180, 1e-3)
 42    pipe_data = DoubleUTube(1, 0.015, 0.02, 0.4, 0.05)
 43
 44    borefield_gt = gt.boreholes.rectangle_field(10, 12, 6, 6, 100, 1, 0.075)
 45
 46    # Monthly loading values
 47    peak_cooling = np.array([0., 0, 34., 69., 133., 187., 213., 240., 160., 37., 0., 0.])  # Peak cooling in kW
 48    peak_heating = np.array([160., 142, 102., 55., 0., 0., 0., 0., 40.4, 85., 119., 136.])  # Peak heating in kW
 49
 50    # annual heating and cooling load
 51    annual_heating_load = 300 * 10 ** 3  # kWh
 52    annual_cooling_load = 160 * 10 ** 3  # kWh
 53
 54    # percentage of annual load per month (15.5% for January ...)
 55    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])
 56    monthly_load_cooling_percentage = np.array([0.025, 0.05, 0.05, .05, .075, .1, .2, .2, .1, .075, .05, .025])
 57
 58    # resulting load per month
 59    monthly_load_heating = annual_heating_load * monthly_load_heating_percentage   # kWh
 60    monthly_load_cooling = annual_cooling_load * monthly_load_cooling_percentage   # kWh
 61
 62    # set the load
 63    load = MonthlyGeothermalLoadAbsolute(monthly_load_heating, monthly_load_cooling, peak_heating, peak_cooling)
 64
 65    # create the borefield object
 66    borefield = Borefield(load=load)
 67
 68    borefield.set_ground_parameters(data)
 69    borefield.set_fluid_parameters(fluid_data)
 70    borefield.set_pipe_parameters(pipe_data)
 71    borefield.Rb = 0.2
 72    borefield.set_borefield(borefield_gt)
 73
 74    # create custom gfunction to speed up the calculation
 75    borefield.create_custom_dataset()
 76
 77    # set temperature boundaries
 78    borefield.set_max_avg_fluid_temperature(16)   # maximum temperature
 79    borefield.set_min_avg_fluid_temperature(0)    # minimum temperature
 80
 81    # size with constant Rb* value
 82    borefield.calculation_setup(use_constant_Rb=True)
 83
 84    # calculate the Rb* value
 85    borefield.Rb = borefield.borehole.calculate_Rb(100, 1, 0.075, data.k_s)
 86
 87    start_Rb_constant = time.time()
 88    for i in range(number_of_iterations):
 89        # set the load
 90        load = MonthlyGeothermalLoadAbsolute(monthly_load_heating_array[i], monthly_load_cooling_array[i],
 91                                              peak_load_heating_array[i], peak_load_cooling_array[i])
 92        borefield.load = load
 93        results_Rb_static[i] = borefield.size()
 94    end_Rb_constant = time.time()
 95
 96    # size with a dynamic Rb* value
 97    borefield.calculation_setup(use_constant_Rb=False)
 98
 99    start_Rb_dynamic = time.time()
100    for i in range(number_of_iterations):
101        # set the load
102        load = MonthlyGeothermalLoadAbsolute(monthly_load_heating_array[i], monthly_load_cooling_array[i],
103                                              peak_load_heating_array[i], peak_load_cooling_array[i])
104        borefield.load = load
105        results_Rb_dynamic[i] = borefield.size()
106    end_Rb_dynamic = time.time()
107    print(results_Rb_dynamic[1])
108
109    print("These are the results when an inaccurate constant Rb* value is used.")
110    print("Time for sizing with a constant Rb* value:", end_Rb_constant - start_Rb_constant, "s")
111    print("Time for sizing with a dynamic Rb* value:", end_Rb_dynamic - start_Rb_dynamic, "s")
112
113    # calculate differences
114    for i in range(number_of_iterations):
115        difference_results[i] = results_Rb_dynamic[i] - results_Rb_static[i]
116
117    print("The maximal difference between the sizing with a constant and a dynamic Rb* value:", np.round(np.max(difference_results), 3), "m or", np.round(np.max(difference_results) / results_Rb_static[np.argmax(difference_results)] * 100, 3), "% w.r.t. the constant Rb* approach.")
118    print("The mean difference between the sizing with a constant and a dynamic Rb* value:", np.round(np.mean(difference_results), 3), "m or", np.round(np.mean(difference_results) / np.mean(results_Rb_static) * 100, 3), "% w.r.t. the constant Rb* approach.")
119    print("------------------------------------------------------------------------------")
120
121    # Do the same thing but with another constant Rb* value based on a borehole depth of 185m.
122
123    borefield_gt = gt.boreholes.rectangle_field(10, 12, 6, 6, 185, 1, 0.075) # borefield with an accurate guess of 185m for the depth of the borefield
124    borefield.set_borefield(borefield_gt)
125
126    # size with a constant Rb* value
127    borefield.calculation_setup(use_constant_Rb=True)
128
129    # calculate the Rb* value
130    borefield.Rb = borefield.borehole.calculate_Rb(100, 1, 0.075, data.k_s)
131
132    start_Rb_constant = time.time()
133    for i in range(number_of_iterations):
134        # set the load
135        load = MonthlyGeothermalLoadAbsolute(monthly_load_heating_array[i], monthly_load_cooling_array[i],
136                                             peak_load_heating_array[i], peak_load_cooling_array[i])
137        borefield.load = load
138        results_Rb_static[i] = borefield.size()
139    end_Rb_constant = time.time()
140
141    # size with a dynamic Rb* value
142    borefield.calculation_setup(use_constant_Rb=False)
143
144    start_Rb_dynamic = time.time()
145    for i in range(number_of_iterations):
146        # set the load
147        load = MonthlyGeothermalLoadAbsolute(monthly_load_heating_array[i], monthly_load_cooling_array[i],
148                                             peak_load_heating_array[i], peak_load_cooling_array[i])
149        borefield.load = load
150        results_Rb_dynamic[i] = borefield.size()
151    end_Rb_dynamic = time.time()
152
153    print("These are the results when an accurate constant Rb* value is used.")
154    print("Time for sizing with a constant Rb* value:", end_Rb_constant - start_Rb_constant, "s")
155    print("Time for sizing with a dynamic Rb* value:", end_Rb_dynamic - start_Rb_dynamic, "s")
156
157    # calculate differences
158    for i in range(number_of_iterations):
159        difference_results[i] = results_Rb_dynamic[i] - results_Rb_static[i]
160
161    print("The maximal difference between the sizing with a constant and a dynamic Rb* value:",
162          np.round(np.max(difference_results), 3), "m or",
163          np.round(np.max(difference_results) / results_Rb_static[np.argmax(difference_results)] * 100, 3),
164          "% w.r.t. the constant Rb* approach.")
165    print("The mean difference between the sizing with a constant and a dynamic Rb* value:",
166          np.round(np.mean(difference_results), 3), "m or",
167          np.round(np.mean(difference_results) / np.mean(results_Rb_static) * 100, 3),
168          "% w.r.t. the constant Rb* approach.")
169
170
171if __name__ == "__main__":  # pragma: no cover
172    sizing_with_Rb()