Compare the accuracy and speed of different g-function solvers¶
This example compares the simulation times and the accuracy of different solvers for the evaluation of g-functions.
The g-function of a field of 6 by4 boreholes is first calculated for a boundary condition of uniform borehole wall temperature along the boreholes, equal for all boreholes. Three different solvers are compared : ‘detailed’, ‘similarities’ [1] and ‘equivalent’ [2]. Their accuracy and calculation time are compared using the ‘detailed’ solver as a reference. This shows that the ‘similarities’ solver can evaluate g-functions with high accuracy.
The g-function of a field of 12 by 10 boreholes is then calculated for a boundary condition of uniform borehole wall temperature along the boreholes, equal for all boreholes. Two different solvers are compared : ‘similarities’ and ‘equivalent’. The accuracy and calculation time of the ‘equivalent’ is compared using the ‘similarities’ solver as a reference. This shows that the ‘equivalent’ solver evaluates g-functions at a very high calculation speed while maintaining reasonable accuracy.
The script is located in: pygfunction/examples/comparison_gfunction_solvers.py
1# -*- coding: utf-8 -*-
2""" Comparison of solvers for the evaluation of g-functions using uniform and
3 equal borehole wall temperatures.
4
5 The g-function of a field of 6x4 boreholes is calculated for a boundary
6 condition of uniform borehole wall temperature along the boreholes, equal
7 for all boreholes. Three different solvers are compared : 'detailed',
8 'similarities' and 'equivalent'. Their accuracy and calculation time are
9 compared using the 'detailed' solver as a reference. This shows that the
10 'similarities' solver can evaluate g-functions with high accuracy.
11
12 The g-function of a field of 12x10 boreholes is calculated for a boundary
13 condition of uniform borehole wall temperature along the boreholes, equal
14 for all boreholes. Two different solvers are compared : 'similarities' and
15 'equivalent'. The accuracy and calculation time of the 'equivalent' is
16 compared using the 'similarities' solver as a reference. This shows that
17 the 'equivalent' solver evaluates g-functions at a very high calculation
18 speed while maintaining reasonable accuracy.
19
20"""
21import matplotlib.pyplot as plt
22import numpy as np
23from time import perf_counter
24
25import pygfunction as gt
26
27
28def main():
29 # -------------------------------------------------------------------------
30 # Simulation parameters
31 # -------------------------------------------------------------------------
32
33 # Borehole dimensions
34 D = 4.0 # Borehole buried depth (m)
35 H = 150.0 # Borehole length (m)
36 r_b = 0.075 # Borehole radius (m)
37 B = 7.5 # Borehole spacing (m)
38
39 # Thermal properties
40 alpha = 1.0e-6 # Ground thermal diffusivity (m2/s)
41
42 # g-Function calculation options
43 options = {'nSegments': 8,
44 'disp': True}
45
46 # Geometrically expanding time vector.
47 dt = 100*3600. # Time step
48 tmax = 3000. * 8760. * 3600. # Maximum time
49 Nt = 15 # Number of time steps
50 ts = H**2/(9.*alpha) # Bore field characteristic time
51 time = gt.utilities.time_geometric(dt, tmax, Nt)
52 lntts = np.log(time/ts)
53
54 # -------------------------------------------------------------------------
55 # Borehole field (First bore field)
56 # -------------------------------------------------------------------------
57
58 # Field of 6x4 (n=24) boreholes
59 N_1 = 6
60 N_2 = 4
61 borefield = gt.borefield.Borefield.rectangle_field(
62 N_1, N_2, B, B, H, D, r_b)
63
64 # -------------------------------------------------------------------------
65 # Evaluate g-functions
66 # -------------------------------------------------------------------------
67 t0 = perf_counter()
68 gfunc_detailed = gt.gfunction.gFunction(
69 borefield, alpha, time=time, options=options, method='detailed')
70 t1 = perf_counter()
71 t_detailed = t1 - t0
72 gfunc_similarities = gt.gfunction.gFunction(
73 borefield, alpha, time=time, options=options, method='similarities')
74 t2 = perf_counter()
75 t_similarities = t2 - t1
76 gfunc_equivalent = gt.gfunction.gFunction(
77 borefield, alpha, time=time, options=options, method='equivalent')
78 t3 = perf_counter()
79 t_equivalent = t3 - t2
80
81 # -------------------------------------------------------------------------
82 # Plot results
83 # -------------------------------------------------------------------------
84 # Draw g-functions
85 ax = gfunc_detailed.visualize_g_function().axes[0]
86 ax.plot(lntts, gfunc_similarities.gFunc, 'bx')
87 ax.plot(lntts, gfunc_equivalent.gFunc, 'ro')
88 ax.legend([f'detailed (t = {t_detailed:.3f} sec)',
89 f'similarities (t = {t_similarities:.3f} sec)',
90 f'equivalent (t = {t_equivalent:.3f} sec)'])
91 ax.set_title(f'Field of {N_1} by {N_2} boreholes')
92 plt.tight_layout()
93
94 # Draw absolute error
95 # Configure figure and axes
96 fig = gt.utilities._initialize_figure()
97 ax = fig.add_subplot(111)
98 # Axis labels
99 ax.set_xlabel(r'ln$(t/t_s)$')
100 ax.set_ylabel(r'Absolute error')
101 gt.utilities._format_axes(ax)
102 # Absolute error
103 ax.plot(lntts, np.abs(gfunc_similarities.gFunc - gfunc_detailed.gFunc),
104 '-', label='similarities')
105 ax.plot(lntts, np.abs(gfunc_equivalent.gFunc - gfunc_detailed.gFunc),
106 '--', label='equivalent')
107 ax.legend()
108 ax.set_title(f"Absolute error relative to the 'detailed' solver "
109 f"(Field of {N_1} by {N_2} boreholes)")
110 # Adjust to plot window
111 fig.tight_layout()
112
113 # Draw relative error
114 # Configure figure and axes
115 fig = gt.utilities._initialize_figure()
116 ax = fig.add_subplot(111)
117 # Axis labels
118 ax.set_xlabel(r'ln$(t/t_s)$')
119 ax.set_ylabel(r'Relative error')
120 gt.utilities._format_axes(ax)
121 # Relative error
122 gFunc_ref = gfunc_detailed.gFunc # reference g-function
123 ax.plot(lntts, (gfunc_similarities.gFunc - gFunc_ref) / gFunc_ref,
124 '-', label='similarities')
125 ax.plot(lntts, (gfunc_equivalent.gFunc - gFunc_ref) / gFunc_ref,
126 '--', label='equivalent')
127 ax.legend()
128 ax.set_title(f"Relative error relative to the 'detailed' solver "
129 f"(Field of {N_1} by {N_2} boreholes)")
130 # Adjust to plot window
131 fig.tight_layout()
132
133 # -------------------------------------------------------------------------
134 # Borehole field (Second bore field)
135 # -------------------------------------------------------------------------
136
137 # Field of 6x4 (n=24) boreholes
138 N_1 = 12
139 N_2 = 10
140 field = gt.boreholes.rectangle_field(N_1, N_2, B, B, H, D, r_b)
141
142 # -------------------------------------------------------------------------
143 # Evaluate g-functions
144 # -------------------------------------------------------------------------
145 gfunc_similarities = gt.gfunction.gFunction(
146 field, alpha, time=time, options=options, method='similarities')
147 t2 = perf_counter()
148 t_similarities = t2 - t1
149 gfunc_equivalent = gt.gfunction.gFunction(
150 field, alpha, time=time, options=options, method='equivalent')
151 t3 = perf_counter()
152 t_equivalent = t3 - t2
153
154 # -------------------------------------------------------------------------
155 # Plot results
156 # -------------------------------------------------------------------------
157 # Draw g-functions
158 ax = gfunc_similarities.visualize_g_function().axes[0]
159 ax.plot(lntts, gfunc_equivalent.gFunc, 'ro')
160 ax.legend([f'similarities (t = {t_similarities:.3f} sec)',
161 f'equivalent (t = {t_equivalent:.3f} sec)'])
162 ax.set_title(f'Field of {N_1} by {N_2} boreholes')
163 plt.tight_layout()
164
165 # Draw absolute error
166 # Configure figure and axes
167 fig = gt.utilities._initialize_figure()
168 ax = fig.add_subplot(111)
169 # Axis labels
170 ax.set_xlabel(r'ln$(t/t_s)$')
171 ax.set_ylabel(r'Absolute error')
172 gt.utilities._format_axes(ax)
173 # Absolute error
174 ax.plot(lntts, np.abs(gfunc_equivalent.gFunc - gfunc_similarities.gFunc),
175 label='equivalent')
176 ax.legend()
177 ax.set_title(f"Absolute error relative to the 'similarities' solver "
178 f"(Field of {N_1} by {N_2} boreholes)")
179 # Adjust to plot window
180 fig.tight_layout()
181
182 # Draw relative error
183 # Configure figure and axes
184 fig = gt.utilities._initialize_figure()
185 ax = fig.add_subplot(111)
186 # Axis labels
187 ax.set_xlabel(r'ln$(t/t_s)$')
188 ax.set_ylabel(r'Relative error')
189 gt.utilities._format_axes(ax)
190 # Relative error
191 ax.plot(lntts, (gfunc_equivalent.gFunc - gfunc_similarities.gFunc) / gfunc_similarities.gFunc,
192 label='equivalent')
193 ax.legend()
194 ax.set_title(f"Relative error relative to the 'similarities' solver "
195 f"(Field of {N_1} by {N_2} boreholes)")
196 # Adjust to plot window
197 fig.tight_layout()
198
199 return
200
201
202# Main function
203if __name__ == '__main__':
204 main()
References