Source code for iwfm.nearest_node

# nearest_node.py
# Read IWFM well file and return nearest IWFM node to an (x,y) location
# the nearest node to each (x,y) point
# Copyright (C) 2020-2026 University of California
# -----------------------------------------------------------------------------
# This information is free; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This work is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# For a copy of the GNU General Public License, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# -----------------------------------------------------------------------------


'''Read IWFM well file and return nearest IWFM node to an (x,y) location the nearest node to each (x,y) point.'''

[docs] def nearest_node(point, node_set): '''Find the nearest node to a point from the node array. Parameters ---------- point : tuple (x,y) point node_set : list list of [node_id, x, y] entries Returns ------- nearest : int node id of the nearest node, or -1 if node_set is empty ''' import math dist, nearest = 9.9e30, -1 for j in range(0, len(node_set)): line = node_set[j] pt = [line[1], line[2]] # Compute distance between each pair of the two collections of inputs. new_dist = math.hypot(point[0] - pt[0], point[1] - pt[1]) # Euclidean distance if dist > new_dist: dist, nearest = new_dist, line[0] return nearest
def read_well_points(well_file): '''Read well locations from a text file. Accepts comma- or whitespace-separated lines of ``ID X Y`` (extra columns ignored). Comment lines starting with C, c, * or # and a non-numeric header line are skipped. Parameters ---------- well_file : str well location file name Returns ------- wells : list [well_id (str), x (float), y (float)] per well ''' wells = [] with open(well_file, encoding='utf-8') as f: for line in f: line = line.strip() if not line or line[0] in 'Cc*#': continue parts = line.replace(',', ' ').split() if len(parts) < 3: continue try: wells.append([parts[0], float(parts[1]), float(parts[2])]) except ValueError: continue # header or other non-numeric line return wells if __name__ == '__main__': ' Run nearest_node() from command line ' import math import sys import iwfm.debug as idb import iwfm from iwfm.debug import parse_cli_flags verbose, debug = parse_cli_flags() if len(sys.argv) > 1: # arguments are listed on the command line node_file = sys.argv[1] well_file = sys.argv[2] out_file = sys.argv[3] if len(sys.argv) > 3 else well_file.rsplit('.', 1)[0] + '_nodes.csv' else: # ask for file names from terminal node_file = input('IWFM Node file name: ') well_file = input('Well file name (ID, X, Y): ') out_file = input('Output file name: ') iwfm.file_test(node_file) iwfm.file_test(well_file) idb.exe_time() # initialize timer node_coord, node_list, factor = iwfm.iwfm_read_nodes(node_file) node_set = [[n[0], n[1] * factor, n[2] * factor] for n in node_coord] node_xy = {n[0]: (n[1], n[2]) for n in node_set} wells = read_well_points(well_file) if not wells: print(f' No well locations found in {well_file}') sys.exit(1) with open(out_file, 'w', encoding='utf-8') as f: f.write('WellID,X,Y,NearestNode,Distance\n') for well_id, x, y in wells: nearest = nearest_node((x, y), node_set) nx, ny = node_xy[nearest] distance = math.hypot(x - nx, y - ny) f.write(f'{well_id},{x},{y},{nearest},{distance:.2f}\n') print(f' Wrote nearest nodes for {len(wells)} wells to {out_file}') idb.exe_time() # print elapsed time