Calculation of g-Functions computed with non-uniform segment lengthsΒΆ
This example demonstrates the use of the utilities
module to determine discretized segment ratios along a borehole.
The following script computes g-Functions for a field of 6x4 boreholes utilizing the MIFT and UBWT boundary conditions with a 48 segments per borehole and equal segment lengths. The MIFT and UBWT g-functions are computed with only 8 segments per borehole and non-uniform segment lengths. RMSE values are compared. It is shown that g-functions can be calculated accurately using a small number of segments.
The script is located in: pygfunction/examples/discretize_boreholes.py
1# -*- coding: utf-8 -*-
2""" Example of g-function calculation using non-uniform segment lengths along
3 the boreholes.
4
5 The g-functions of a field of 6x4 boreholes are calculated for two
6 boundary conditions : (1) a uniform borehole wall temperature along the
7 boreholes equal for all boreholes, and (2) an equal inlet fluid
8 temperature into the boreholes. g-Functions using 8 segments in a
9 non-uniform discretization are compared to reference g-functions
10 calculated using 48 segments of equal lengths. It is shown that g-functions
11 can be calculated accurately using a small number of segments.
12"""
13
14import matplotlib.pyplot as plt
15import numpy as np
16from numpy import pi
17
18import pygfunction as gt
19
20
21def main():
22 # -------------------------------------------------------------------------
23 # Simulation parameters
24 # -------------------------------------------------------------------------
25
26 # Borehole dimensions
27 D = 4.0 # Borehole buried depth (m)
28 H = 150.0 # Borehole length (m)
29 r_b = 0.075 # Borehole radius (m)
30 B = 7.5 # Borehole spacing (m)
31
32 # Pipe dimensions
33 r_out = 0.0211 # Pipe outer radius (m)
34 r_in = 0.0147 # Pipe inner radius (m)
35 D_s = 0.052 # Shank spacing (m)
36 epsilon = 1.0e-6 # Pipe roughness (m)
37
38 # Pipe positions
39 # Single U-tube [(x_in, y_in), (x_out, y_out)]
40 pos_pipes = [(-D_s, 0.), (D_s, 0.)]
41
42 # Ground properties
43 alpha = 1.0e-6 # Ground thermal diffusivity (m2/s)
44 k_s = 2.0 # Ground thermal conductivity (W/m.K)
45
46 # Grout properties
47 k_g = 1.0 # Grout thermal conductivity (W/m.K)
48
49 # Pipe properties
50 k_p = 0.4 # Pipe thermal conductivity (W/m.K)
51
52 # Fluid properties
53 m_flow_borehole = 0.25 # Total fluid mass flow rate per borehole (kg/s)
54 # The fluid is propylene-glycol (20 %) at 20 degC
55 fluid = gt.media.Fluid('MPG', 20.)
56 cp_f = fluid.cp # Fluid specific isobaric heat capacity (J/kg.K)
57 rho_f = fluid.rho # Fluid density (kg/m3)
58 mu_f = fluid.mu # Fluid dynamic viscosity (kg/m.s)
59 k_f = fluid.k # Fluid thermal conductivity (W/m.K)
60
61 # g-Function calculation options
62
63 # Number of segments used in the reference calculation with uniform
64 # discretization
65 nSegments_uniform = 48
66 options_uniform = {'nSegments': nSegments_uniform,
67 'segment_ratios': None,
68 'disp': True}
69 # Number of segments used in the calculation with non-uniform
70 # discretization
71 nSegments_unequal = 8
72 segment_ratios = gt.utilities.segment_ratios(
73 nSegments_unequal, end_length_ratio=0.02)
74 options_unequal = {'nSegments': nSegments_unequal,
75 'segment_ratios': segment_ratios,
76 'disp':True}
77
78 # Geometrically expanding time vector.
79 dt = 100*3600. # Time step
80 tmax = 3000. * 8760. * 3600. # Maximum time
81 Nt = 25 # Number of time steps
82 ts = H**2/(9.*alpha) # Bore field characteristic time
83 time = gt.utilities.time_geometric(dt, tmax, Nt)
84
85 # -------------------------------------------------------------------------
86 # Borehole field
87 # -------------------------------------------------------------------------
88
89 # Field of 6x4 (n=24) boreholes
90 N_1 = 6
91 N_2 = 4
92 borefield = gt.borefield.Borefield.rectangle_field(
93 N_1, N_2, B, B, H, D, r_b)
94 gt.boreholes.visualize_field(borefield)
95 nBoreholes = len(borefield)
96
97 # -------------------------------------------------------------------------
98 # Initialize pipe model
99 # -------------------------------------------------------------------------
100
101 # Pipe thermal resistance
102 R_p = gt.pipes.conduction_thermal_resistance_circular_pipe(
103 r_in, r_out, k_p)
104 # Fluid to inner pipe wall thermal resistance (Single U-tube)
105 m_flow_pipe = m_flow_borehole
106 h_f = gt.pipes.convective_heat_transfer_coefficient_circular_pipe(
107 m_flow_pipe, r_in, mu_f, rho_f, k_f, cp_f, epsilon)
108 R_f = 1.0/(h_f*2*pi*r_in)
109
110 # Single U-tube, same for all boreholes in the bore field
111 UTubes = []
112 for borehole in borefield:
113 SingleUTube = gt.pipes.SingleUTube(
114 pos_pipes, r_in, r_out, borehole, k_s, k_g, R_f + R_p)
115 UTubes.append(SingleUTube)
116 m_flow_network = m_flow_borehole*nBoreholes
117
118 # Network of boreholes connected in parallel
119 network = gt.networks.Network(borefield, UTubes)
120
121 # -------------------------------------------------------------------------
122 # Evaluate the g-functions for the borefield
123 # -------------------------------------------------------------------------
124
125 # Compute g-function for the converged MIFT case with equal number of
126 # segments per borehole, and equal segment lengths along the boreholes
127 gfunc_MIFT_uniform = gt.gfunction.gFunction(
128 network, alpha, time=time, m_flow_network=m_flow_network, cp_f=cp_f,
129 boundary_condition='MIFT', options=options_uniform)
130
131 # Calculate the g-function for uniform borehole wall temperature
132 gfunc_UBWT_uniform = gt.gfunction.gFunction(
133 borefield, alpha, time=time, boundary_condition='UBWT',
134 options=options_uniform)
135
136 # Compute g-function for the MIFT case with equal number of segments per
137 # borehole, and non-uniform segment lengths along the boreholes
138 gfunc_MIFT_unequal = gt.gfunction.gFunction(
139 network, alpha, time=time, m_flow_network=m_flow_network, cp_f=cp_f,
140 boundary_condition='MIFT', options=options_unequal)
141
142 # Calculate the g-function for uniform borehole wall temperature
143 gfunc_UBWT_unequal = gt.gfunction.gFunction(
144 borefield, alpha, time=time, boundary_condition='UBWT',
145 options=options_unequal)
146
147 # Compute the rmse between the reference cases and the discretized
148 # (predicted) cases
149 RMSE_MIFT = RMSE(gfunc_MIFT_uniform.gFunc, gfunc_MIFT_unequal.gFunc)
150 print(f'RMSE (MIFT) = {RMSE_MIFT:.5f}')
151 RMSE_UBWT = RMSE(gfunc_UBWT_uniform.gFunc, gfunc_UBWT_unequal.gFunc)
152 print(f'RMSE (UBWT) = {RMSE_UBWT:.5f}')
153
154 # -------------------------------------------------------------------------
155 # Plot g-functions
156 # -------------------------------------------------------------------------
157
158 ax = gfunc_MIFT_uniform.visualize_g_function().axes[0]
159 ax.plot(np.log(time / ts), gfunc_UBWT_uniform.gFunc)
160 ax.plot(np.log(time / ts), gfunc_MIFT_unequal.gFunc, 'o')
161 ax.plot(np.log(time / ts), gfunc_UBWT_unequal.gFunc, 'o')
162 ax.legend(
163 ['Equal inlet temperature (uniform segments)',
164 'Uniform borehole wall temperature (uniform segments)',
165 'Equal inlet temperature (non-uniform segments)',
166 'Uniform borehole wall temperature (non-uniform segments)'])
167 plt.tight_layout()
168
169 return
170
171
172def RMSE(reference, predicted):
173 rmse = np.linalg.norm(predicted - reference) / len(reference)
174 return rmse
175
176
177# Main function
178if __name__ == '__main__':
179 main()