diff --git a/pygfunction/examples/issue78-compare_detailed.py b/pygfunction/examples/issue78-compare_detailed.py deleted file mode 100644 index 7a7c0778..00000000 --- a/pygfunction/examples/issue78-compare_detailed.py +++ /dev/null @@ -1,230 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Develop new functions to find similarties by adding an intermediate step with -comparisons of segments (instead of going straight to segments). -""" - -import time as tim - -import matplotlib.pyplot as plt -from matplotlib.ticker import AutoMinorLocator -import numpy as np -from scipy.integrate import quad, quad_vec -from scipy.special import erf -from functools import partial -from multiprocessing import Pool - -import pygfunction as gt - -def main(): - out = [] - # ------------------------------------------------------------------------- - # Simulation parameters - # ------------------------------------------------------------------------- - - # Borehole dimensions - D = 4.0 # Borehole buried depth (m) - H = 150.0 # Borehole length (m) - r_b = 0.075 # Borehole radius (m) - B = 7.5 # Borehole spacing (m) - - # Number of segments per borehole - nSegments = 12 - - # Thermal properties - alpha = 1.0e-6 # Ground thermal diffusivity (m2/s) - - # Geometrically expanding time vector. - dt = 100*3600. # Time step - tmax = 3000. * 8760. * 3600. # Maximum time - Nt = 25 # Number of time steps - ts = H**2/(9.*alpha) # Bore field characteristic time - time = gt.utilities.time_geometric(dt, tmax, Nt) - - # ------------------------------------------------------------------------- - # Compare all rectangular fields from 1 by 1 to 5 by 5 with the - # existing detailed method using 12 segments - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True} - N_min = 1 - N_max = 5 - time_rectangular = [[], []] - gFunc_new_rectangular = [] - gFunc_old_rectangular = [] - N_rectangular = [] - for N_1 in range(N_min, N_max+1): - for N_2 in range(N_1, N_max+1): - print(' Field of {} by {} boreholes '.format(N_1, N_2).center(60, '=')) - boreholes = gt.boreholes.rectangle_field(N_1, N_2, B, B, H, D, r_b) - N_rectangular.append(len(boreholes)) - tic = tim.time() - gfunc_new = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc0 = tim.time() - gfunc_old = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='detailed', options=options) - toc1 = tim.time() - time_rectangular[0].append(toc0 - tic) - time_rectangular[1].append(toc1 - toc0) - gFunc_new_rectangular.append(gfunc_new.gFunc) - gFunc_old_rectangular.append(gfunc_old.gFunc) - - fig = _initialize_figure() - ax1 = fig.add_subplot(111) - ax1.set_xlabel(r'Number of boreholes') - ax1.set_ylabel(r'Calculation time [sec]') - ax1.set_title('Rectangular fields up to {} by {} (Detailed solver)'.format(N_max, N_max)) - _format_axes(ax1) - ax1.loglog(N_rectangular, time_rectangular[0], 'o', label='New') - ax1.loglog(N_rectangular, time_rectangular[1], 'x', label='Old') - ax1.legend() - plt.tight_layout() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{old}$') - ax2.set_ylabel(r'$g_{new} - g_{old}$') - ax2.set_title('Rectangular fields up to {} by {} (Detailed solver)'.format(N_max, N_max)) - _format_axes(ax2) - for (g_new, g_old) in zip(gFunc_new_rectangular, gFunc_old_rectangular): - ax2.plot(g_old, g_new - g_old, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare fields of 3 by 3 boreholes with increasing number of segments - # ------------------------------------------------------------------------- - boreholes = gt.boreholes.rectangle_field(3, 3, B, B, H, D, r_b) - time_segments = [[], []] - gFunc_new_segments = [] - gFunc_old_segments = [] - N_segments = [] - for n in [1, 3, 6, 12]: - nSegments = n - options = {'nSegments':nSegments, 'disp':True} - print(' Field of 3 by 3 boreholes ({} segments) '.format(nSegments).center(60, '=')) - N_segments.append(nSegments) - tic = tim.time() - gfunc_new = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc0 = tim.time() - gfunc_old = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='detailed', options=options) - toc1 = tim.time() - time_segments[0].append(toc0 - tic) - time_segments[1].append(toc1 - toc0) - gFunc_new_segments.append(gfunc_new.gFunc) - gFunc_old_segments.append(gfunc_old.gFunc) - - fig = _initialize_figure() - ax1 = fig.add_subplot(111) - ax1.set_xlabel(r'Number of segments') - ax1.set_ylabel(r'Calculation time [sec]') - ax1.set_title('Field of 3 by 3 boreholes (nSegments) (Detailed solver)') - _format_axes(ax1) - ax1.loglog(N_segments, time_segments[0], 'o', label='New') - ax1.loglog(N_segments, time_segments[1], 'x', label='Old') - ax1.legend() - plt.tight_layout() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{old}$') - ax2.set_ylabel(r'$g_{new} - g_{old}$') - ax2.set_title('Field of 3 by 3 boreholes (nSegments) (Detailed solver)') - _format_axes(ax2) - for (g_new, g_old) in zip(gFunc_new_segments, gFunc_old_segments): - ax2.plot(g_old, g_new - g_old, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare field of 5 uneven boreholes - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True, 'profiles':True} - H_all = np.array([150., 85., 150., 175., 125.]) - x_all = np.array([0., 5., 12.5, 17.5, 25.]) - boreholes = [gt.boreholes.Borehole(Hi, D, r_b, xi, 0.) for (Hi, xi) in zip(H_all, x_all)] - H_mean = np.mean([b.H for b in boreholes]) - ts = H_mean**2/(9*alpha) - - time_uneven = [[], []] - gFunc_new_uneven = [] - gFunc_old_uneven = [] - print(' Field of 5 uneven boreholes '.format().center(60, '=')) - tic = tim.time() - gfunc_new = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc0 = tim.time() - gfunc_old = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='detailed', options=options) - toc1 = tim.time() - time_uneven[0].append(toc0 - tic) - time_uneven[1].append(toc1 - toc0) - gFunc_new_uneven.append(gfunc_new.gFunc) - gFunc_old_uneven.append(gfunc_old.gFunc) - - ax = gfunc_new.visualize_g_function().axes[0] - ax.plot(np.log(gfunc_old.time/ts), gfunc_old.gFunc, 'kx') - ax.legend(['New, t = {:.2f} sec'.format(toc0 - tic), 'Old, t = {:.2f} sec'.format(toc1 - toc0)]) - ax.set_title('Field of 5 uneven boreholes (Detailed solver)') - plt.tight_layout() - - gfunc_new.visualize_heat_extraction_rate_profiles() - gfunc_old.visualize_heat_extraction_rate_profiles() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{old}$') - ax2.set_ylabel(r'$g_{new} - g_{old}$') - ax2.set_title('Field of 5 uneven boreholes (Detailed solver)') - _format_axes(ax2) - for (g_new, g_old) in zip(gFunc_new_uneven, gFunc_old_uneven): - ax2.plot(g_old, g_new - g_old, 'o') - plt.tight_layout() - - fig = gt.boreholes.visualize_field(boreholes) - - return - -def _initialize_figure(): - """ - Initialize a matplotlib figure object with overwritten default - parameters. - - Returns - ------- - fig : figure - Figure object (matplotlib). - - """ - plt.rc('font', size=9) - plt.rc('xtick', labelsize=9) - plt.rc('ytick', labelsize=9) - plt.rc('lines', lw=1.5, markersize=5.0) - plt.rc('savefig', dpi=500) - fig = plt.figure() - return fig - -def _format_axes(ax): - """ - Adjust axis parameters. - - Parameters - ---------- - ax : axis - Axis object (amtplotlib). - - """ - from matplotlib.ticker import AutoMinorLocator - # Draw major and minor tick marks inwards - ax.tick_params( - axis='both', which='both', direction='in', - bottom=True, top=True, left=True, right=True) - # Auto-adjust minor tick marks - ax.xaxis.set_minor_locator(AutoMinorLocator()) - ax.yaxis.set_minor_locator(AutoMinorLocator()) - return - - -# Main function -if __name__ == '__main__': - out = main() diff --git a/pygfunction/examples/issue78-compare_similarities.py b/pygfunction/examples/issue78-compare_similarities.py deleted file mode 100644 index 4ac6275f..00000000 --- a/pygfunction/examples/issue78-compare_similarities.py +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Develop new functions to find similarties by adding an intermediate step with -comparisons of segments (instead of going straight to segments). -""" - -import time as tim - -import matplotlib.pyplot as plt -from matplotlib.ticker import AutoMinorLocator -import numpy as np -from scipy.integrate import quad, quad_vec -from scipy.special import erf -from functools import partial -from multiprocessing import Pool - -import pygfunction as gt - -def main(): - out = [] - # ------------------------------------------------------------------------- - # Simulation parameters - # ------------------------------------------------------------------------- - - # Borehole dimensions - D = 4.0 # Borehole buried depth (m) - H = 150.0 # Borehole length (m) - r_b = 0.075 # Borehole radius (m) - B = 7.5 # Borehole spacing (m) - - # Number of segments per borehole - nSegments = 12 - - # Thermal properties - alpha = 1.0e-6 # Ground thermal diffusivity (m2/s) - - # Geometrically expanding time vector. - dt = 100*3600. # Time step - tmax = 3000. * 8760. * 3600. # Maximum time - Nt = 25 # Number of time steps - ts = H**2/(9.*alpha) # Bore field characteristic time - time = gt.utilities.time_geometric(dt, tmax, Nt) - - # ------------------------------------------------------------------------- - # Compare all rectangular fields from 1 by 1 to 12 by 12 with the - # existing similarities method using 12 segments - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True} - N_min = 1 - N_max = 12 - time_rectangular = [[], []] - gFunc_new_rectangular = [] - gFunc_old_rectangular = [] - N_rectangular = [] - for N_1 in range(N_min, N_max+1): - for N_2 in range(N_1, N_max+1): - print(' Field of {} by {} boreholes '.format(N_1, N_2).center(60, '=')) - boreholes = gt.boreholes.rectangle_field(N_1, N_2, B, B, H, D, r_b) - N_rectangular.append(len(boreholes)) - tic = tim.time() - gfunc_new = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_old = gt.gfunction.gFunction( - boreholes, alpha, time=time, options=options) - toc1 = tim.time() - time_rectangular[0].append(toc0 - tic) - time_rectangular[1].append(toc1 - toc0) - gFunc_new_rectangular.append(gfunc_new.gFunc) - gFunc_old_rectangular.append(gfunc_old.gFunc) - - fig = _initialize_figure() - ax1 = fig.add_subplot(111) - ax1.set_xlabel(r'Number of boreholes') - ax1.set_ylabel(r'Calculation time [sec]') - ax1.set_title('Rectangular fields up to {} by {}'.format(N_max, N_max)) - _format_axes(ax1) - ax1.loglog(N_rectangular, time_rectangular[0], 'o', label='New') - ax1.loglog(N_rectangular, time_rectangular[1], 'x', label='Old') - ax1.legend() - plt.tight_layout() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{old}$') - ax2.set_ylabel(r'$g_{new} - g_{old}$') - ax2.set_title('Rectangular fields up to {} by {}'.format(N_max, N_max)) - _format_axes(ax2) - for (g_new, g_old) in zip(gFunc_new_rectangular, gFunc_old_rectangular): - ax2.plot(g_old, g_new - g_old, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare fields of 5 by 5 boreholes with increasing number of segments - # ------------------------------------------------------------------------- - boreholes = gt.boreholes.rectangle_field(5, 5, B, B, H, D, r_b) - time_segments = [[], []] - gFunc_new_segments = [] - gFunc_old_segments = [] - N_segments = [] - for n in range(0, 6): - nSegments = 2**n - options = {'nSegments':nSegments, 'disp':True} - print(' Field of 5 by 5 boreholes ({} segments) '.format(nSegments).center(60, '=')) - N_segments.append(nSegments) - tic = tim.time() - gfunc_new = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_old = gt.gfunction.gFunction( - boreholes, alpha, time=time, options=options) - toc1 = tim.time() - time_segments[0].append(toc0 - tic) - time_segments[1].append(toc1 - toc0) - gFunc_new_segments.append(gfunc_new.gFunc) - gFunc_old_segments.append(gfunc_old.gFunc) - - fig = _initialize_figure() - ax1 = fig.add_subplot(111) - ax1.set_xlabel(r'Number of segments') - ax1.set_ylabel(r'Calculation time [sec]') - ax1.set_title('Field of 5 by 5 boreholes (nSegments)') - _format_axes(ax1) - ax1.loglog(N_segments, time_segments[0], 'o', label='New') - ax1.loglog(N_segments, time_segments[1], 'x', label='Old') - ax1.legend() - plt.tight_layout() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{old}$') - ax2.set_ylabel(r'$g_{new} - g_{old}$') - ax2.set_title('Field of 5 by 5 boreholes (nSegments)') - _format_axes(ax2) - for (g_new, g_old) in zip(gFunc_new_segments, gFunc_old_segments): - ax2.plot(g_old, g_new - g_old, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare field of 6 by 6 boreholes with outer ring of boreholes of - # reduced length (totalling 10 by 10 boreholes) - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True, 'profiles':True} - boreholes = gt.boreholes.rectangle_field(6, 6, B, B, H, D, r_b) - boreholes1 = gt.boreholes.box_shaped_field(8, 8, B, B, 85., D, r_b) - boreholes2 = gt.boreholes.box_shaped_field(10, 10, B, B, 85., D, r_b) - for b in boreholes1: - b.x = b.x - B - b.y = b.y - B - for b in boreholes2: - b.x = b.x - 2*B - b.y = b.y - 2*B - boreholes = boreholes + boreholes1 + boreholes2 - H_mean = np.mean([b.H for b in boreholes]) - ts = H_mean**2/(9*alpha) - - time_uneven = [[], []] - gFunc_new_uneven = [] - gFunc_old_uneven = [] - print(' Field of 6 by 6 boreholes with outer ring '.format(nSegments).center(60, '=')) - tic = tim.time() - gfunc_new = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_old = gt.gfunction.gFunction( - boreholes, alpha, time=time, options=options) - toc1 = tim.time() - time_uneven[0].append(toc0 - tic) - time_uneven[1].append(toc1 - toc0) - gFunc_new_uneven.append(gfunc_new.gFunc) - gFunc_old_uneven.append(gfunc_old.gFunc) - - ax = gfunc_new.visualize_g_function().axes[0] - ax.plot(np.log(gfunc_old.time/ts), gfunc_old.gFunc, 'kx') - ax.legend(['New, t = {:.2f} sec'.format(toc0 - tic), 'Old, t = {:.2f} sec'.format(toc1 - toc0)]) - ax.set_title('Field of 6 by 6 boreholes with outer ring') - plt.tight_layout() - - gfunc_new.visualize_heat_extraction_rate_profiles(iBoreholes=[0, 36, 64]) - gfunc_old.visualize_heat_extraction_rate_profiles(iBoreholes=[0, 36, 64]) - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{old}$') - ax2.set_ylabel(r'$g_{new} - g_{old}$') - ax2.set_title('Field of 6 by 6 boreholes with outer ring') - _format_axes(ax2) - for (g_new, g_old) in zip(gFunc_new_uneven, gFunc_old_uneven): - ax2.plot(g_old, g_new - g_old, 'o') - plt.tight_layout() - - fig = gt.boreholes.visualize_field(boreholes) - - return - -def _initialize_figure(): - """ - Initialize a matplotlib figure object with overwritten default - parameters. - - Returns - ------- - fig : figure - Figure object (matplotlib). - - """ - plt.rc('font', size=9) - plt.rc('xtick', labelsize=9) - plt.rc('ytick', labelsize=9) - plt.rc('lines', lw=1.5, markersize=5.0) - plt.rc('savefig', dpi=500) - fig = plt.figure() - return fig - -def _format_axes(ax): - """ - Adjust axis parameters. - - Parameters - ---------- - ax : axis - Axis object (amtplotlib). - - """ - from matplotlib.ticker import AutoMinorLocator - # Draw major and minor tick marks inwards - ax.tick_params( - axis='both', which='both', direction='in', - bottom=True, top=True, left=True, right=True) - # Auto-adjust minor tick marks - ax.xaxis.set_minor_locator(AutoMinorLocator()) - ax.yaxis.set_minor_locator(AutoMinorLocator()) - return - - -# Main function -if __name__ == '__main__': - out = main() diff --git a/pygfunction/examples/issue78-compare_solvers.py b/pygfunction/examples/issue78-compare_solvers.py deleted file mode 100644 index b86578fc..00000000 --- a/pygfunction/examples/issue78-compare_solvers.py +++ /dev/null @@ -1,280 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Develop new functions to find similarties by adding an intermediate step with -comparisons of segments (instead of going straight to segments). -""" - -import time as tim - -import matplotlib.pyplot as plt -from matplotlib.ticker import AutoMinorLocator -import numpy as np -from scipy.integrate import quad, quad_vec -from scipy.special import erf -from functools import partial -from multiprocessing import Pool - -import pygfunction as gt - -def main(): - out = [] - # ------------------------------------------------------------------------- - # Simulation parameters - # ------------------------------------------------------------------------- - - # Borehole dimensions - D = 4.0 # Borehole buried depth (m) - H = 150.0 # Borehole length (m) - r_b = 0.075 # Borehole radius (m) - B = 7.5 # Borehole spacing (m) - - # Number of segments per borehole - nSegments = 12 - - # Thermal properties - alpha = 1.0e-6 # Ground thermal diffusivity (m2/s) - - # Geometrically expanding time vector. - dt = 100*3600. # Time step - tmax = 3000. * 8760. * 3600. # Maximum time - Nt = 25 # Number of time steps - ts = H**2/(9.*alpha) # Bore field characteristic time - time = gt.utilities.time_geometric(dt, tmax, Nt) - - # ------------------------------------------------------------------------- - # Compare all rectangular fields from 1 by 1 to 12 by 12 - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True} - N_min = 1 - N_max = 12 - time_rectangular = [[], []] - gFunc_sim_rectangular = [] - gFunc_det_rectangular = [] - N_rectangular = [] - for N_1 in range(N_min, N_max+1): - for N_2 in range(N_1, N_max+1): - print(' Field of {} by {} boreholes '.format(N_1, N_2).center(60, '=')) - boreholes = gt.boreholes.rectangle_field(N_1, N_2, B, B, H, D, r_b) - N_rectangular.append(len(boreholes)) - tic = tim.time() - gfunc_sim = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_det = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc1 = tim.time() - time_rectangular[0].append(toc0 - tic) - time_rectangular[1].append(toc1 - toc0) - gFunc_sim_rectangular.append(gfunc_sim.gFunc) - gFunc_det_rectangular.append(gfunc_det.gFunc) - - fig = _initialize_figure() - ax1 = fig.add_subplot(111) - ax1.set_xlabel(r'Number of boreholes') - ax1.set_ylabel(r'Calculation time [sec]') - ax1.set_title('Rectangular fields up to {} by {}'.format(N_max, N_max)) - _format_axes(ax1) - ax1.loglog(N_rectangular, time_rectangular[0], 'o', label='Similarities') - ax1.loglog(N_rectangular, time_rectangular[1], 'x', label='Detailed') - ax1.legend() - plt.tight_layout() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{detailed}$') - ax2.set_ylabel(r'$g_{similarities} - g_{detailed}$') - ax2.set_title('Rectangular fields up to {} by {}'.format(N_max, N_max)) - _format_axes(ax2) - for (g_sim, g_det) in zip(gFunc_sim_rectangular, gFunc_det_rectangular): - ax2.plot(g_det, g_sim - g_det, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare fields of 5 by 5 boreholes with increasing number of segments - # ------------------------------------------------------------------------- - boreholes = gt.boreholes.rectangle_field(5, 5, B, B, H, D, r_b) - time_segments = [[], []] - gFunc_sim_segments = [] - gFunc_det_segments = [] - N_segments = [] - for n in range(0, 6): - nSegments = 2**n - options = {'nSegments':nSegments, 'disp':True} - print(' Field of 5 by 5 boreholes ({} segments) '.format(nSegments).center(60, '=')) - N_segments.append(nSegments) - tic = tim.time() - gfunc_sim = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_det = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc1 = tim.time() - time_segments[0].append(toc0 - tic) - time_segments[1].append(toc1 - toc0) - gFunc_sim_segments.append(gfunc_sim.gFunc) - gFunc_det_segments.append(gfunc_det.gFunc) - - fig = _initialize_figure() - ax1 = fig.add_subplot(111) - ax1.set_xlabel(r'Number of segments') - ax1.set_ylabel(r'Calculation time [sec]') - ax1.set_title('Field of 5 by 5 boreholes (nSegments)') - _format_axes(ax1) - ax1.loglog(N_segments, time_segments[0], 'o', label='Similarities') - ax1.loglog(N_segments, time_segments[1], 'x', label='Detailed') - ax1.legend() - plt.tight_layout() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{detailed}$') - ax2.set_ylabel(r'$g_{similarities} - g_{detailed}$') - ax2.set_title('Field of 5 by 5 boreholes (nSegments)') - _format_axes(ax2) - for (g_sim, g_det) in zip(gFunc_sim_segments, gFunc_det_segments): - ax2.plot(g_det, g_sim - g_det, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare field of 6 by 6 boreholes with outer ring of boreholes of - # reduced length (totalling 10 by 10 boreholes) - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True, 'profiles':True} - boreholes = gt.boreholes.rectangle_field(6, 6, B, B, H, D, r_b) - boreholes1 = gt.boreholes.box_shaped_field(8, 8, B, B, 85., D, r_b) - boreholes2 = gt.boreholes.box_shaped_field(10, 10, B, B, 85., D, r_b) - for b in boreholes1: - b.x = b.x - B - b.y = b.y - B - for b in boreholes2: - b.x = b.x - 2*B - b.y = b.y - 2*B - boreholes = boreholes + boreholes1 + boreholes2 - H_mean = np.mean([b.H for b in boreholes]) - ts = H_mean**2/(9*alpha) - - time_uneven = [[], []] - gFunc_sim_uneven = [] - gFunc_det_uneven = [] - print(' Field of 6 by 6 boreholes with outer ring '.format(nSegments).center(60, '=')) - tic = tim.time() - gfunc_sim = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_det = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc1 = tim.time() - time_uneven[0].append(toc0 - tic) - time_uneven[1].append(toc1 - toc0) - gFunc_sim_uneven.append(gfunc_sim.gFunc) - gFunc_det_uneven.append(gfunc_det.gFunc) - - ax = gfunc_sim.visualize_g_function().axes[0] - ax.plot(np.log(gfunc_det.time/ts), gfunc_det.gFunc, 'kx') - ax.legend(['Similarities, t = {:.2f} sec'.format(toc0 - tic), 'Detailed, t = {:.2f} sec'.format(toc1 - toc0)]) - ax.set_title('Field of 6 by 6 boreholes with outer ring') - plt.tight_layout() - - gfunc_sim.visualize_heat_extraction_rate_profiles(iBoreholes=[0, 36, 64]) - gfunc_det.visualize_heat_extraction_rate_profiles(iBoreholes=[0, 36, 64]) - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{detailed}$') - ax2.set_ylabel(r'$g_{similarities} - g_{detailed}$') - ax2.set_title('Field of 6 by 6 boreholes with outer ring') - _format_axes(ax2) - for (g_sim, g_det) in zip(gFunc_sim_uneven, gFunc_det_uneven): - ax2.plot(g_det, g_sim - g_det, 'o') - plt.tight_layout() - - # ------------------------------------------------------------------------- - # Compare field of 5 uneven boreholes - # ------------------------------------------------------------------------- - options = {'nSegments':12, 'disp':True, 'profiles':True} - H_all = np.array([150., 85., 150., 175., 125.]) - x_all = np.array([0., 5., 12.5, 17.5, 25.]) - boreholes = [gt.boreholes.Borehole(Hi, D, r_b, xi, 0.) for (Hi, xi) in zip(H_all, x_all)] - H_mean = np.mean([b.H for b in boreholes]) - ts = H_mean**2/(9*alpha) - - time_uneven2 = [[], []] - gFunc_sim_uneven2 = [] - gFunc_det_uneven2 = [] - print(' Field of 5 uneven boreholes '.format().center(60, '=')) - tic = tim.time() - gfunc_sim = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-similarities', options=options) - toc0 = tim.time() - gfunc_det = gt.gfunction.gFunction( - boreholes, alpha, time=time, method='new-detailed', options=options) - toc1 = tim.time() - time_uneven2[0].append(toc0 - tic) - time_uneven2[1].append(toc1 - toc0) - gFunc_sim_uneven2.append(gfunc_sim.gFunc) - gFunc_det_uneven2.append(gfunc_det.gFunc) - - ax = gfunc_sim.visualize_g_function().axes[0] - ax.plot(np.log(gfunc_det.time/ts), gfunc_det.gFunc, 'kx') - ax.legend(['Similarities, t = {:.2f} sec'.format(toc0 - tic), 'Detailed, t = {:.2f} sec'.format(toc1 - toc0)]) - ax.set_title('Field of 5 uneven boreholes') - plt.tight_layout() - - gfunc_sim.visualize_heat_extraction_rate_profiles() - gfunc_det.visualize_heat_extraction_rate_profiles() - - fig = _initialize_figure() - ax2 = fig.add_subplot(111) - ax2.set_xlabel(r'$g_{detailed}$') - ax2.set_ylabel(r'$g_{similarities} - g_{detailed}$') - ax2.set_title('Field of 5 uneven boreholes') - _format_axes(ax2) - for (g_sim, g_det) in zip(gFunc_sim_uneven2, gFunc_det_uneven2): - ax2.plot(g_det, g_sim - g_det, 'o') - plt.tight_layout() - - return - -def _initialize_figure(): - """ - Initialize a matplotlib figure object with overwritten default - parameters. - - Returns - ------- - fig : figure - Figure object (matplotlib). - - """ - plt.rc('font', size=9) - plt.rc('xtick', labelsize=9) - plt.rc('ytick', labelsize=9) - plt.rc('lines', lw=1.5, markersize=5.0) - plt.rc('savefig', dpi=500) - fig = plt.figure() - return fig - -def _format_axes(ax): - """ - Adjust axis parameters. - - Parameters - ---------- - ax : axis - Axis object (amtplotlib). - - """ - from matplotlib.ticker import AutoMinorLocator - # Draw major and minor tick marks inwards - ax.tick_params( - axis='both', which='both', direction='in', - bottom=True, top=True, left=True, right=True) - # Auto-adjust minor tick marks - ax.xaxis.set_minor_locator(AutoMinorLocator()) - ax.yaxis.set_minor_locator(AutoMinorLocator()) - return - - -# Main function -if __name__ == '__main__': - out = main() diff --git a/pygfunction/gfunction.py b/pygfunction/gfunction.py index 786977cd..f4f27c70 100644 --- a/pygfunction/gfunction.py +++ b/pygfunction/gfunction.py @@ -1,8 +1,6 @@ from __future__ import absolute_import, division, print_function import time as tim -from functools import partial -from multiprocessing import Pool import matplotlib.pyplot as plt import numpy as np @@ -150,18 +148,10 @@ def __init__(self, boreholes_or_network, alpha, time=None, self.solver = _Similarities( self.boreholes, self.network, self.time, self.boundary_condition, **self.options) - elif self.method.lower()=='new-similarities': - self.solver = _NewSimilarities( - self.boreholes, self.network, self.time, - self.boundary_condition, **self.options) elif self.method.lower()=='detailed': self.solver = _Detailed( self.boreholes, self.network, self.time, self.boundary_condition, **self.options) - elif self.method.lower()=='new-detailed': - self.solver = _NewDetailed( - self.boreholes, self.network, self.time, - self.boundary_condition, **self.options) else: raise ValueError('\'{}\' is not a valid method.'.format(method)) @@ -768,7 +758,7 @@ def _check_inputs(self): "Boundary condition \'{}\' is not an acceptable boundary condition. \n" \ "Please provide one of the following inputs : {}".format( self.boundary_condition, acceptable_boundary_conditions) - acceptable_methods = ['detailed', 'new-detailed', 'similarities', 'new-similarities'] + acceptable_methods = ['detailed', 'similarities'] assert type(self.method) is str and self.method in acceptable_methods, \ "Method \'{}\' is not an acceptable method. \n" \ "Please provide one of the following inputs : {}".format( @@ -1199,6 +1189,9 @@ class _BaseSolver(object): Interpolation method used for segment-to-segment thermal response factors. See documentation for scipy.interpolate.interp1d. Default is 'linear'. + dtype : numpy dtype, optional + numpy data type used for matrices and vectors. + Default is numpy.double. """ def __init__(self, boreholes, network, time, boundary_condition, @@ -1568,172 +1561,6 @@ class _Detailed(_BaseSolver): modeled as a series of finite line source segments, as proposed in [#Detailed-CimBer2014]_. - Parameters - ---------- - boreholes : list of Borehole objects - List of boreholes included in the bore field. - network : network object - Model of the network. - time : float or array - Values of time (in seconds) for which the g-function is evaluated. - boundary_condition : str - Boundary condition for the evaluation of the g-function. Should be one - of - - - 'UHTR' : - **Uniform heat transfer rate**. This is corresponds to boundary - condition *BC-I* as defined by Cimmino and Bernier (2014) - [#Detailed-CimBer2014]_. - - 'UBWT' : - **Uniform borehole wall temperature**. This is corresponds to - boundary condition *BC-III* as defined by Cimmino and Bernier - (2014) [#Detailed-CimBer2014]_. - - 'MIFT' : - **Mixed inlet fluid temperatures**. This boundary condition was - introduced by Cimmino (2015) [#gFunction-Cimmin2015]_ for - parallel-connected boreholes and extended to mixed - configurations by Cimmino (2019) [#Detailed-Cimmin2019]_. - - nSegments : int, optional - Number of line segments used per borehole. - Default is 12. - processes : int, optional - Number of processors to use in calculations. If the value is set to - None, a number of processors equal to cpu_count() is used. - Default is None. - disp : bool, optional - Set to true to print progression messages. - Default is False. - profiles : bool, optional - Set to true to keep in memory the temperatures and heat extraction - rates. - Default is False. - kind : string, optional - Interpolation method used for segment-to-segment thermal response - factors. See documentation for scipy.interpolate.interp1d. - Default is 'linear'. - - References - ---------- - .. [#Detailed-CimBer2014] Cimmino, M., & Bernier, M. (2014). A - semi-analytical method to generate g-functions for geothermal bore - fields. International Journal of Heat and Mass Transfer, 70, 641-650. - .. [#Detailed-Cimmin2019] Cimmino, M. (2019). Semi-analytical method for - g-function calculation of bore fields with series- and - parallel-connected boreholes. Science and Technology for the Built - Environment, 25 (8), 1007-1022. - - """ - def initialize(self, **kwargs): - """ - Split boreholes into segments. - - Returns - ------- - nSources : int - Number of finite line heat sources in the borefield used to - initialize the matrix of segment-to-segment thermal response - factors (of size: nSources x nSources). - - """ - # Split boreholes into segments - self.boreSegments = self.borehole_segments() - nSources = len(self.boreSegments) - return nSources - - def thermal_response_factors(self, time, alpha, kind='linear'): - """ - Evaluate the segment-to-segment thermal response factors for all pairs - of segments in the borefield at all time steps using the finite line - source solution. - - This method returns a scipy.interpolate.interp1d object of the matrix - of thermal response factors, containing a copy of the matrix accessible - by h_ij.y[:nSources,:nSources,:nt+1]. The first index along the - third axis corresponds to time t=0. The interp1d object can be used to - obtain thermal response factors at any intermediat time by - h_ij(t)[:nSources,:nSources]. - - Attributes - ---------- - time : float or array - Values of time (in seconds) for which the g-function is evaluated. - alpha : float - Soil thermal diffusivity (in m2/s). - kind : string, optional - Interpolation method used for segment-to-segment thermal response - factors. See documentation for scipy.interpolate.interp1d. - Default is 'linear'. - - Returns - ------- - h_ij : interp1d - interp1d object (scipy.interpolate) of the matrix of - segment-to-segment thermal response factors. - - """ - if self.disp: - print('Calculating segment to segment response factors ...', - end='') - # Number of time values - nt = len(np.atleast_1d(time)) - # Prepare pool of workers for parallel computation - pool = Pool(processes=self.processes) - # Initialize chrono - tic = tim.time() - # Initialize segment-to-segment response factors - h_ij = np.zeros((self.nSources, self.nSources, nt), dtype=self.dtype) - - for i in range(self.nSources): - # Segment to same-segment thermal response factor - # FLS solution for combined real and image sources - b2 = self.boreSegments[i] - func = partial(finite_line_source, - alpha=alpha, borehole1=b2, borehole2=b2) - # Evaluate the FLS solution at all times in parallel - h = np.array(pool.map(func, time), dtype=self.dtype) - h_ij[i, i, :] = h - - # Segment to other segments thermal response factor - for j in range(i+1, self.nSources): - b1 = self.boreSegments[j] - # Evaluate the FLS solution at all times in parallel - func = partial(finite_line_source, - alpha=alpha, borehole1=b1, borehole2=b2) - h = np.array(pool.map(func, time), dtype=self.dtype) - h_ij[i, j, :] = h - h_ij[j, i, :] = b2.H / b1.H * h_ij[i, j, :] - - # Close pool of workers - pool.close() - pool.join() - - # Return 2d array if time is a scalar - if np.isscalar(time): - h_ij = h_ij[:,:,0] - - # Interp1d object for thermal response factors - h_ij = interp1d( - np.hstack((0., time)), - np.dstack( - (np.zeros((self.nSources,self.nSources), dtype=self.dtype), - h_ij)), - kind=kind, copy=True, axis=2) - toc = tim.time() - if self.disp: print(' {:.3f} sec'.format(toc - tic)) - - return h_ij - - -class _NewDetailed(_BaseSolver): - """ - Detailed solver for the evaluation of the g-function. - - This solver superimposes the finite line source (FLS) solution to - estimate the g-function of a geothermal bore field. Each borehole is - modeled as a series of finite line source segments, as proposed in - [#Detailed-CimBer2014]_. - Parameters ---------- boreholes : list of Borehole objects @@ -1778,6 +1605,9 @@ class _NewDetailed(_BaseSolver): Interpolation method used for segment-to-segment thermal response factors. See documentation for scipy.interpolate.interp1d. Default is linear. + dtype : numpy dtype, optional + numpy data type used for matrices and vectors. + Default is numpy.double. References ---------- @@ -1911,490 +1741,6 @@ def _borehole_segments_one_borehole(self, borehole, nSegments): class _Similarities(_BaseSolver): - """ - Detailed solver for the evaluation of the g-function. - - This solver superimposes the finite line source (FLS) solution to - estimate the g-function of a geothermal bore field. Each borehole is - modeled as a series of finite line source segments, as proposed in - [#Similarities-CimBer2014]_. The number of evaluations of the FLS solution - is decreased by identifying similar pairs of boreholes, for which the same - FLS value can be applied [#Similarities-Cimmin2018]_. - - Parameters - ---------- - boreholes : list of Borehole objects - List of boreholes included in the bore field. - network : network object - Model of the network. - time : float or array - Values of time (in seconds) for which the g-function is evaluated. - boundary_condition : str - Boundary condition for the evaluation of the g-function. Should be one - of - - - 'UHTR' : - **Uniform heat transfer rate**. This is corresponds to boundary - condition *BC-I* as defined by Cimmino and Bernier (2014) - [#Similarities-CimBer2014]_. - - 'UBWT' : - **Uniform borehole wall temperature**. This is corresponds to - boundary condition *BC-III* as defined by Cimmino and Bernier - (2014) [#Similarities-CimBer2014]_. - - 'MIFT' : - **Mixed inlet fluid temperatures**. This boundary condition was - introduced by Cimmino (2015) [#Similarities-Cimmin2015]_ for - parallel-connected boreholes and extended to mixed - configurations by Cimmino (2019) [#Similarities-Cimmin2019]_. - - nSegments : int, optional - Number of line segments used per borehole. - Default is 12. - processes : int, optional - Number of processors to use in calculations. If the value is set to - None, a number of processors equal to cpu_count() is used. - Default is None. - disp : bool, optional - Set to true to print progression messages. - Default is False. - profiles : bool, optional - Set to true to keep in memory the temperatures and heat extraction - rates. - Default is False. - kind : string, optional - Interpolation method used for segment-to-segment thermal response - factors. See documentation for scipy.interpolate.interp1d. - Default is 'linear'. - disTol : float, optional - Relative tolerance on radial distance. Two distances - (d1, d2) between two pairs of boreholes are considered equal if the - difference between the two distances (abs(d1-d2)) is below tolerance. - Default is 0.01. - tol : float, optional - Relative tolerance on length and depth. Two lengths H1, H2 - (or depths D1, D2) are considered equal if abs(H1 - H2)/H2 < tol. - Default is 1.0e-6. - - References - ---------- - .. [#Similarities-CimBer2014] Cimmino, M., & Bernier, M. (2014). A - semi-analytical method to generate g-functions for geothermal bore - fields. International Journal of Heat and Mass Transfer, 70, 641-650. - .. [#Similarities-Cimmin2015] Cimmino, M. (2015). The effects of borehole - thermal resistances and fluid flow rate on the g-functions of geothermal - bore fields. International Journal of Heat and Mass Transfer, 91, - 1119-1127. - .. [#Similarities-Cimmin2018] Cimmino, M. (2018). Fast calculation of the - g-functions of geothermal borehole fields using similarities in the - evaluation of the finite line source solution. Journal of Building - Performance Simulation, 11 (6), 655-668. - .. [#Similarities-Cimmin2019] Cimmino, M. (2019). Semi-analytical method - for g-function calculation of bore fields with series- and - parallel-connected boreholes. Science and Technology for the Built - Environment, 25 (8), 1007-1022. - - """ - def initialize(self, disTol=0.01, tol=1.0e-6, **kwargs): - """ - Split boreholes into segments and identify similarities in the - borefield. - - Returns - ------- - nSources : int - Number of finite line heat sources in the borefield used to - initialize the matrix of segment-to-segment thermal response - factors (of size: nSources x nSources). - - """ - self.disTol = disTol - self.tol = tol - # Check the validity of inputs - self._check_solver_specific_inputs() - # Real and image FLS solutions are only split for numbers of segments - # greater than 1 - self.splitRealAndImage = self.nSegments > 1 - # Split boreholes into segments - self.boreSegments = self.borehole_segments() - # Initialize similarities - self.find_similarities() - return len(self.boreSegments) - - def thermal_response_factors(self, time, alpha, kind='linear'): - """ - Evaluate the segment-to-segment thermal response factors for all pairs - of segments in the borefield at all time steps using the finite line - source solution. - - This method returns a scipy.interpolate.interp1d object of the matrix - of thermal response factors, containing a copy of the matrix accessible - by h_ij.y[:nSources,:nSources,:nt+1]. The first index along the - third axis corresponds to time t=0. The interp1d object can be used to - obtain thermal response factors at any intermediat time by - h_ij(t)[:nSources,:nSources]. - - Attributes - ---------- - time : float or array - Values of time (in seconds) for which the g-function is evaluated. - alpha : float - Soil thermal diffusivity (in m2/s). - kind : string, optional - Interpolation method used for segment-to-segment thermal response - factors. See documentation for scipy.interpolate.interp1d. - Default is linear. - - Returns - ------- - h_ij : interp1d - interp1d object (scipy.interpolate) of the matrix of - segment-to-segment thermal response factors. - - """ - if self.disp: - print('Calculating segment to segment response factors ...', - end='') - # Number of time values - nt = len(np.atleast_1d(time)) - # Prepare pool of workers for parallel computation - pool = Pool(processes=self.processes) - # Initialize chrono - tic = tim.time() - # Initialize segment-to-segment response factors - h_ij = np.zeros((self.nSources, self.nSources, nt), dtype=self.dtype) - - # Similarities for real sources - for s in range(self.nSimPos): - n1 = self.simPos[s][0][0] - n2 = self.simPos[s][0][1] - b1 = self.boreSegments[n1] - b2 = self.boreSegments[n2] - if self.splitRealAndImage: - # FLS solution for real source only - func = partial(finite_line_source, - alpha=alpha, borehole1=b1, borehole2=b2, - reaSource=True, imgSource=False) - else: - # FLS solution for combined real and image sources - func = partial(finite_line_source, - alpha=alpha, borehole1=b1, borehole2=b2, - reaSource=True, imgSource=True) - # Evaluate the FLS solution at all times in parallel - hPos = np.array( - pool.map(func, np.atleast_1d(time)), dtype=self.dtype) - # Assign thermal response factors to similar segment pairs - for (i, j) in self.simPos[s]: - h_ij[j, i, :] = hPos - h_ij[i, j, :] = b2.H/b1.H * hPos - - # Similarities for image sources (only if splitRealAndImage=True) - if self.splitRealAndImage: - for s in range(self.nSimNeg): - n1 = self.simNeg[s][0][0] - n2 = self.simNeg[s][0][1] - b1 = self.boreSegments[n1] - b2 = self.boreSegments[n2] - # FLS solution for image source only - func = partial(finite_line_source, - alpha=alpha, borehole1=b1, borehole2=b2, - reaSource=False, imgSource=True) - # Evaluate the FLS solution at all times in parallel - hNeg = np.array( - pool.map(func, np.atleast_1d(time)), dtype=self.dtype) - # Assign thermal response factors to similar segment pairs - for (i, j) in self.simNeg[s]: - h_ij[j, i, :] = h_ij[j, i, :] + hNeg - h_ij[i, j, :] = b2.H/b1.H * h_ij[j, i, :] - - # Close pool of workers - pool.close() - pool.join() - - # Return 2d array if time is a scalar - if np.isscalar(time): - h_ij = h_ij[:,:,0] - - # Interp1d object for thermal response factors - h_ij = interp1d( - np.hstack( - (0., time)), - np.dstack( - (np.zeros((self.nSources,self.nSources), dtype=self.dtype), - h_ij)), kind=kind, copy=True, axis=2) - toc = tim.time() - if self.disp: print(' {:.3f} sec'.format(toc - tic)) - - return h_ij - - def find_similarities(self): - """ - Find similarities in the FLS solution for groups of boreholes. - - This function identifies pairs of boreholes for which the evaluation - of the Finite Line Source (FLS) solution is equivalent. - - """ - if self.disp: print('Identifying similarities ...', - end='') - # Initialize chrono - tic = tim.time() - # Initialize pool of workers - pool = Pool(processes=self.processes) - - # Group pairs of boreholes by radial distance - (nDis, disPairs, nPairs, pairs) = self.group_by_distance() - - # If real and image parts of the FLS are split, evaluate real and image - # similarities separately: - if self.splitRealAndImage: - # Evaluate similarities for each distance in parallel - func = partial(self.find_similarities_one_distance, kind='real') - realSims = pool.map(func, pairs) - - # Evaluate similarities for each distance in parallel - func = partial(self.find_similarities_one_distance, kind='image') - imageSims = pool.map(func, pairs) - - # Otherwise, evaluate the combined real+image FLS similarities - else: - func = partial( - self.find_similarities_one_distance, kind='realandimage') - # Evaluate symmetries for each distance in parallel - realSims = pool.map(func, pairs) - - # Close pool of workers - pool.close() - pool.join() - - # Aggregate real similarities for all distances - self.nSimPos = 0 - self.simPos = [] - self.HSimPos = [] - self.DSimPos = [] - self.disSimPos = [] - for i in range(nDis): - realSim = realSims[i] - nSim = realSim[0] - self.nSimPos += nSim - self.disSimPos += [disPairs[i] for _ in range(nSim)] - self.simPos += realSim[1] - self.HSimPos += realSim[2] - self.DSimPos += realSim[3] - - # Aggregate image similarities for all distances - self.nSimNeg = 0 - self.simNeg = [] - self.HSimNeg = [] - self.DSimNeg = [] - self.disSimNeg = [] - if self.splitRealAndImage: - for i in range(nDis): - imageSim = imageSims[i] - nSim = imageSim[0] - self.nSimNeg += nSim - self.disSimNeg += [disPairs[i] for _ in range(nSim)] - self.simNeg += imageSim[1] - self.HSimNeg += imageSim[2] - self.DSimNeg += imageSim[3] - - # Stop chrono - toc = tim.time() - if self.disp: print(' {:.3f} sec'.format(toc - tic)) - - return - - def find_similarities_one_distance(self, pairs, kind): - """ - Evaluate similarities for all pairs of boreholes separated by the same - radial distance. - - Parameters - ---------- - pairs : list - List of tuples of the borehole indices of borehole pairs at each - radial distance. - kind : string - Type of similarity to be evaluated - - 'real' : similarity in real sources - - 'image' : similarity in image sources - - 'realandimage' : similarity for combined real and image - sources. - - Returns - ------- - nSim : int - Number of similarities. - sim : list - For each similarity, a list of pairs (tuple) of borehole indices - is returned. - HSim : list - List of lengths (tuple) of the pairs of boreholes in each - similarity. - DSim : list - List of depths (tuple) of the pairs of boreholes in each - similarity. - - """ - # Condition for equivalence of the real part of the FLS solution - def compare_real_segments(H1a, H1b, H2a, H2b, D1a, - D1b, D2a, D2b, tol): - if (abs((H1a-H1b)/H1a) < tol and - abs((H2a-H2b)/H2a) < tol and - abs(((D2a-D1a)-(D2b-D1b))/(D2a-D1a+1e-30)) < tol): - similarity = True - else: - similarity = False - return similarity - - # Condition for equivalence of the image part of the FLS solution - def compare_image_segments(H1a, H1b, H2a, H2b, - D1a, D1b, D2a, D2b, tol): - if (abs((H1a-H1b)/H1a) < tol and - abs((H2a-H2b)/H2a) < tol and - abs(((D2a+D1a)-(D2b+D1b))/(D2a+D1a+1e-30)) < tol): - similarity = True - else: - similarity = False - return similarity - - # Condition for equivalence of the full FLS solution - def compare_realandimage_segments(H1a, H1b, H2a, H2b, - D1a, D1b, D2a, D2b, - tol): - if (abs((H1a-H1b)/H1a) < tol and - abs((H2a-H2b)/H2a) < tol and - abs((D1a-D1b)/(D1a+1e-30)) < tol and - abs((D2a-D2b)/(D2a+1e-30)) < tol): - similarity = True - else: - similarity = False - return similarity - - # Initialize comparison function based on input argument - if kind.lower() == 'real': - # Check real part of FLS - compare_segments = compare_real_segments - elif kind.lower() == 'image': - # Check image part of FLS - compare_segments = compare_image_segments - elif kind.lower() == 'realandimage': - # Check full real+image FLS - compare_segments = compare_realandimage_segments - else: - raise NotImplementedError( - "Error: '{}' not implemented.".format(kind.lower())) - - # Initialize symmetries - nSim = 1 - pair0 = pairs[0] - i0 = pair0[0] - j0 = pair0[1] - sim = [[pair0]] - HSim = [(self.boreSegments[i0].H, self.boreSegments[j0].H)] - DSim = [(self.boreSegments[i0].D, self.boreSegments[j0].D)] - - # Cycle through all pairs of boreholes for the given distance - for pair in pairs[1:]: - ibor = pair[0] - jbor = pair[1] - b1 = self.boreSegments[ibor] - b2 = self.boreSegments[jbor] - # Verify if the current pair should be included in the - # previously identified symmetries - for k in range(nSim): - H1 = HSim[k][0] - H2 = HSim[k][1] - D1 = DSim[k][0] - D2 = DSim[k][1] - if compare_segments(H1, b1.H, H2, b2.H, - D1, b1.D, D2, b2.D, self.tol): - sim[k].append((ibor, jbor)) - break - elif compare_segments(H1, b2.H, H2, b1.H, - D1, b2.D, D2, b1.D, self.tol): - sim[k].append((jbor, ibor)) - break - - else: - # Add symmetry to list if no match was found - nSim += 1 - sim.append([pair]) - HSim.append((b1.H, b2.H)) - DSim.append((b1.D, b2.D)) - return nSim, sim, HSim, DSim - - def group_by_distance(self): - """ - Group pairs of boreholes by radial distance between borehole. - - Returns - ------- - nDis : int - Number of unique radial distances between pairs of borehole. - disPairs : list - List of radial distances. - nPairs : list - List of number of pairs for each radial distance. - pairs : list - List of tuples of the borehole indices of borehole pairs at each - radial distance. - - """ - # Initialize lists - nPairs = [1] - pairs = [[(0, 0)]] - disPairs = [self.boreSegments[0].r_b] - nDis = 1 - - nb = len(self.boreSegments) - for i in range(nb): - b1 = self.boreSegments[i] - # The first segment does not have to be compared to itself - if i == 0: - i2 = i + 1 - else: - i2 = i - - for j in range(i2, nb): - b2 = self.boreSegments[j] - # Distance between current pair of boreholes - dis = b1.distance(b2) - if i == j: - # The relative tolerance is used for same-borehole - # distances - rTol = self.tol * b1.r_b - else: - rTol = self.disTol*dis - # Verify if the current pair should be included in the - # previously identified symmetries - for k in range(nDis): - if abs(disPairs[k] - dis) < rTol: - pairs[k].append((i, j)) - nPairs[k] += 1 - break - - else: - # Add symmetry to list if no match was found - nDis += 1 - disPairs.append(dis) - pairs.append([(i, j)]) - nPairs.append(1) - return nDis, disPairs, nPairs, pairs - - def _check_solver_specific_inputs(self): - """ - This method ensures that solver specific inputs to the Solver object - are what is expected. - - """ - assert type(self.disTol) is float and self.disTol > 0., \ - "The distance tolerance 'disTol' should be a positive float." - assert type(self.tol) is float and self.tol > 0., \ - "The relative tolerance 'tol' should be a positive float." - return - - -class _NewSimilarities(_BaseSolver): """ Similarities solver for the evaluation of the g-function. @@ -2449,6 +1795,9 @@ class _NewSimilarities(_BaseSolver): Interpolation method used for segment-to-segment thermal response factors. See documentation for scipy.interpolate.interp1d. Default is linear. + dtype : numpy dtype, optional + numpy data type used for matrices and vectors. + Default is numpy.double. disTol : float, optional Relative tolerance on radial distance. Two distances (d1, d2) between two pairs of boreholes are considered equal if the