From 033c9acd14d447cc4a73fc457491c42118f21a76 Mon Sep 17 00:00:00 2001 From: MassimoCimmino Date: Sun, 1 Dec 2024 05:26:38 -0500 Subject: [PATCH] Implement Borefield.visualize_field --- examples/custom_bore_field.py | 6 +- examples/custom_bore_field_from_file.py | 2 +- examples/regular_bore_field.py | 4 +- pygfunction/borefield.py | 92 +++++++++++++++++++++++++ pygfunction/boreholes.py | 11 +-- 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/examples/custom_bore_field.py b/examples/custom_bore_field.py index 0048d22..d3703ee 100644 --- a/examples/custom_bore_field.py +++ b/examples/custom_bore_field.py @@ -35,14 +35,14 @@ def main(): # ------------------------------------------------------------------------- # Find and remove duplicates from borehole field # ------------------------------------------------------------------------- - - borefield = gt.boreholes.remove_duplicates(borefield, disp=True) + borefield = gt.borefield.Borefield.from_boreholes( + gt.boreholes.remove_duplicates(borefield, disp=True)) # ------------------------------------------------------------------------- # Draw bore field # ------------------------------------------------------------------------- - gt.boreholes.visualize_field(borefield) + borefield.visualize_field(borefield) return diff --git a/examples/custom_bore_field_from_file.py b/examples/custom_bore_field_from_file.py index da4e299..f97a469 100644 --- a/examples/custom_bore_field_from_file.py +++ b/examples/custom_bore_field_from_file.py @@ -24,7 +24,7 @@ def main(): # Draw bore field # ------------------------------------------------------------------------- - gt.boreholes.visualize_field(borefield) + borefield.visualize_field() return diff --git a/examples/regular_bore_field.py b/examples/regular_bore_field.py index 0224e1c..8012d56 100644 --- a/examples/regular_bore_field.py +++ b/examples/regular_bore_field.py @@ -59,10 +59,10 @@ def main(): # ------------------------------------------------------------------------- # Draw bore fields # ------------------------------------------------------------------------- - for field in [ + for borefield in [ rectangle_field, staggered_rectangle_field, dense_rectangle_field, box_shaped_field, U_shaped_field, L_shaped_field, circle_field]: - gt.boreholes.visualize_field(field) + borefield.visualize_field() plt.show() return diff --git a/pygfunction/borefield.py b/pygfunction/borefield.py index d4b94cf..af8ea71 100644 --- a/pygfunction/borefield.py +++ b/pygfunction/borefield.py @@ -2,10 +2,12 @@ from typing import Union, List, Dict, Tuple from typing_extensions import Self # for compatibility with Python <= 3.10 +import matplotlib.pyplot as plt import numpy as np import numpy.typing as npt from .boreholes import Borehole +from .utilities import _initialize_figure, _format_axes, _format_axes_3d class Borefield: """ @@ -302,6 +304,96 @@ def evaluate_g_function( return gfunc.gFunc + def visualize_field( + self, viewTop=True, view3D=True, labels=True, showTilt=True): + """ + Plot the top view and 3D view of borehole positions. + + Parameters + ---------- + viewTop : bool, optional + Set to True to plot top view. + Default is True + view3D : bool, optional + Set to True to plot 3D view. + Default is True + labels : bool, optional + Set to True to annotate borehole indices to top view plot. + Default is True + showTilt : bool, optional + Set to True to show borehole inclination on top view plot. + Default is True + + Returns + ------- + fig : figure + Figure object (matplotlib). + + """ + # Configure figure and axes + fig = _initialize_figure() + if viewTop and view3D: + ax1 = fig.add_subplot(121) + ax2 = fig.add_subplot(122, projection='3d') + elif viewTop: + ax1 = fig.add_subplot(111) + elif view3D: + ax2 = fig.add_subplot(111, projection='3d') + if viewTop: + ax1.set_xlabel(r'$x$ [m]') + ax1.set_ylabel(r'$y$ [m]') + ax1.axis('equal') + _format_axes(ax1) + if view3D: + ax2.set_xlabel(r'$x$ [m]') + ax2.set_ylabel(r'$y$ [m]') + ax2.set_zlabel(r'$z$ [m]') + _format_axes_3d(ax2) + ax2.invert_zaxis() + + # Bottom end of boreholes + x_H = self.x + self.H * np.sin(self.tilt) * np.cos(self.orientation) + y_H = self.y + self.H * np.sin(self.tilt) * np.sin(self.orientation) + z_H = self.D + self.H * np.cos(self.tilt) + + # ------------------------------------------------------------------------- + # Top view + # ------------------------------------------------------------------------- + if viewTop: + if showTilt: + ax1.plot( + np.stack((self.x, x_H), axis=0), + np.stack((self.y, y_H), axis=0), + 'k--') + ax1.plot(self.x, self.y, 'ko') + if labels: + for i, borehole in enumerate(self): + ax1.text( + borehole.x, + borehole.y, + f' {i}', + ha="left", + va="bottom") + + # ------------------------------------------------------------------------- + # 3D view + # ------------------------------------------------------------------------- + if view3D: + ax2.plot(self.x, self.y, self.D, 'ko') + for i in range(self.nBoreholes): + ax2.plot( + (self.x[i], x_H[i]), + (self.y[i], y_H[i]), + (self.D[i], z_H[i]), + 'k-') + + if viewTop and view3D: + plt.tight_layout(rect=[0, 0.0, 0.90, 1.0]) + else: + plt.tight_layout() + + return fig + def to_boreholes(self) -> List[Borehole]: """ Return a list of boreholes in the bore field. diff --git a/pygfunction/boreholes.py b/pygfunction/boreholes.py index af88642..0cc8e70 100644 --- a/pygfunction/boreholes.py +++ b/pygfunction/boreholes.py @@ -3,7 +3,6 @@ import matplotlib.pyplot as plt import numpy as np -from scipy.constants import pi from scipy.spatial.distance import pdist from .utilities import _initialize_figure, _format_axes, _format_axes_3d @@ -1288,8 +1287,8 @@ def circle_field(N, R, H, D, r_b, tilt=0., origin=None): x0, y0 = origin for i in range(N): - x = R * np.cos(2 * pi * i / N) - y = R * np.sin(2 * pi * i / N) + x = R * np.cos(2 * np.pi * i / N) + y = R * np.sin(2 * np.pi * i / N) orientation = np.arctan2(y - y0, x - x0) # The borehole is inclined only if it does not lie on the origin if np.sqrt((x - x0)**2 + (y - y0)**2) > r_b: @@ -1382,7 +1381,11 @@ def visualize_field( Figure object (matplotlib). """ - from mpl_toolkits.mplot3d import Axes3D + # This function is deprecated as of v2.3. It will be removed in v3.0. + warnings.warn("`pygfunction.boreholes.visualize_field` is " + "deprecated as of v2.3. It will be removed in v3.0. " + "Use the `pygfunction.borefield.Borefield` class instead.", + DeprecationWarning) # Configure figure and axes fig = _initialize_figure()