Source code for pydfnworks.dfnGen.generation.input_checking.user_defined_fracture_functions

import sys
import os
from numpy import pi

from pydfnworks.dfnGen.generation.input_checking.helper_functions import print_error, print_warning

def check_angle_option(angle_option, array):
    for val in array:
        if angle_option == "radian":
            if val > 2 * pi:
                print_warning(
                    "Value greater than 2 PI, angle option of radians has been selected"
                )
        elif angle_option == "degree":
            if val > 360:
                print_warning(
                    "Value greater than 2 PI, angle option of radians has been selected"
                )






[docs] def add_user_fract_from_file(self, filename, shape, nPolygons, by_coord=False, aperture=None, transmissivity=None, permeability=None): """ Sets up paths for fractures defined in user input file. When inserting user fractures from file, hydraulic properties must be provided as a list of length nPolygons (number of fractures defined in the file) Parameters ---------------- filename : string path to source file shape: string The shape of the fracture options are 'rect', 'ell', and 'poly' - Required by_coord : boolean True / False of file format for coordinate or general input nPolygons : int The number of polygons specified in the file permeability : list or array Permeabilities of the fractures transmissivity : list or array Fracture Tramsmissivities aperture : list or array Hydraulic apertures of the fracture Returns --------------- None Notes -------------- Does not write the file, only sets up paths ~/src/dfnworks-aidan/pydfnworks/pydfnworks/ """ fracture_dictionary = {"shape": shape, "filename": filename} hy_prop_type = determine_hy_prop_type(aperture, transmissivity, permeability) fracture_dictionary['aperture'] = aperture fracture_dictionary['transmissivity'] = transmissivity fracture_dictionary['permeability'] = permeability fracture_dictionary['hy_prop_type'] = hy_prop_type fracture_dictionary['nPolygons'] = nPolygons if aperture is not None: if len(aperture) != nPolygons: print_error("Error. aperture list for user fractures from file is not the same length as nPolygons, please check input for add_user_fract_from_file\n") if transmissivity is not None: if len(transmissivity) != nPolygons: print_error("Error. transmissivity list for user fractures from file is not the same length as nPolygons, please check input for add_user_fract_from_file\n") if permeability is not None: if len(permeability) != nPolygons: print_error("Error. aperture list for user fractures from file is not the same length as nPolygons, please check input for add_user_fract_from_file\n") if shape == 'rect': self.params['RectByCoord_Input_File_Path']['value'] = filename if by_coord: self.params['userRectByCoord']['value'] = True else: self.params['userRectanglesOnOff']['value'] = True self.user_rect_params.append(fracture_dictionary) frac_number = len(self.user_rect_params) self.print_user_fracture_information('rect', frac_number - 1) elif shape == 'ell': self.params['EllByCoord_Input_File_Path']['value'] = filename if by_coord: self.params['userEllByCoord']['value'] = True else: self.params['userEllipsesOnOff']['value'] = True self.user_ell_params.append(fracture_dictionary) frac_number = len(self.user_ell_params) self.print_user_fracture_information('ell', frac_number - 1) elif shape == 'poly': # user polygon self.params['userPolygonByCoord']['value'] = True self.params['PolygonByCoord_Input_File_Path']['value'] = filename self.user_poly_params.append(fracture_dictionary) self.print_user_fracture_information('poly') else: print_error( "Error.user fracture shape is not specified correctly, options are 'rect', 'ell', or 'poly'\n" )
[docs] def add_user_fract(self, shape, radii, translation, filename=None, aspect_ratio=1, beta=0, angle_option='degree', orientation_option='normal', normal_vector=None, trend_plunge=None, dip_strike=None, number_of_vertices=None, permeability=None, transmissivity=None, aperture=None): """ Specifies user defined fracture parameters for the DFN. Parameters ------------- shape: string The desired shape of the fracture options are 'rect', 'ell', and 'poly' - Required radii : float 1/2 size of the fracture in meters - Required translation : list of floats [3] Fracture center filename: string The name of the user defined fracture file. Default is user_defined_{shape}.dat aspect_ratio : float Fracture aspect ratio beta : float Rotation angle around center of the fracture angle_option : string Angle option 'degree' or 'radian'. Default is degree orientation_option : string Choice of fracture orienation 'normal', 'trend_plunge', 'dip_strike' normal_vector : list [3] normal vector of the fracture trend_plunge : list [2] trend and plunge of the fracture dip_strike : list [2] dip and strike of the fracture number_of_vertices : int Number of vertices on the fracture boundary. permeability : float Permeability of the fracture transmissivity : float Fracture Tramsmissivity aperture : float Hydraulic aperture of the fracture Returns --------- None - fracture dictionaries are attached to the DFN object Notes ------- Please be aware, the user fracture files can only be automatically written for ellipses and rectangles not specified by coordinate. See https://dfnworks.lanl.gov/dfngen.html#user-defined-fracture-generation-parameters for additional information """ # if specifying details in the python driver file. fracture_dictionary = {"shape": shape} fracture_dictionary['nPolygons'] = 1 # Check input parameters if filename: fracture_dictionary['filename'] = filename else: filename = self.jobname + f"/dfnGen_output/user_defined_{shape}.dat" fracture_dictionary['filename'] = filename # Check radius is positive. if radii > 0: fracture_dictionary['Radii:'] = radii else: print_error( f"Error. Fracture radius must be positive. Value provided {radii}. Exiting." ) # Check Aspect Ratio is positive if aspect_ratio > 0: fracture_dictionary['Aspect_Ratio:'] = aspect_ratio else: print_error( f"Error. Aspect Ratio must be positive. Value provided {aspect_ratio}. Exiting." ) ## check beta Rotation in non-negative. if beta >= 0: fracture_dictionary['Beta:'] = beta else: print_error( f"Error. Beta rotation must be non-negative (>0). Value provided {beta}. Exiting." ) # Check Angle options angle_options = ['radian', 'degree'] if angle_option in angle_options: fracture_dictionary['AngleOption:'] = angle_option else: print_error( f"Error. Unknown angle_option value provided: {angle_option}. Acceptable values are 'radian', 'degree'.\nExiting." ) if len(translation) == 3: fracture_dictionary['Translation:'] = translation else: print_error( f"Error. Fracture Translation (center) must have 3 elements, only {len(translation)} provided.\nValue provided: {translation}. Exiting" ) ## Check orienations and consistency if orientation_option == 'normal': fracture_dictionary['userOrientationOption:'] = 0 if normal_vector: fracture_dictionary['Normal:'] = normal_vector else: print_error( "Error. Requested user fracture orienation 0, but normal vector was not provided. exiting." ) if len(normal_vector) != 3: print_error( f"Error. Normal vector must have 3 elements, only {len(normal_vector)} provided.\nNormal: {normal_vector}. Exiting" ) elif orientation_option == 'trend_plunge': fracture_dictionary['userOrientationOption:'] = 1 if trend_plunge: fracture_dictionary['Trend_Plunge:'] = trend_plunge else: print_error( "Error. Requested user fracture orienation trend_plunge, but trend_plunge was not provided. exiting." ) if len(trend_plunge) != 2: print_error( f"Error. Trend/Plunge must have 2 elements, only {len(trend_plunge)} provided.\trend_plunge: {trend_plunge}. Exiting" ) # Check is angles make sense given radians or degrees print("--> Checking trend_plunge angles") check_angle_option(angle_option, trend_plunge) elif orientation_option == 'dip_strike': fracture_dictionary['userOrientationOption:'] = 2 if dip_strike: fracture_dictionary['Dip_Strike:'] = dip_strike else: print_error( "Error. Requested user fracture orienation dip_strike, but dip_strike was not provided. exiting." ) if len(dip_strike) != 2: print_error( f"Error. Dip/Strike must have 2 elements, only {len(dip_strike)} provided.\trend_plunge: {dip_strike}. Exiting" ) else: print_error( f"Error. Unknown orientation_option provided. Value: {orientation_option}. Options are 'normal', 'trend_plunge', and 'dip_strike'. Exiting" ) # Check is angles make sense given radians or degrees print("--> Checking dip_strike angles") check_angle_option(angle_option, dip_strike) # hydraulic properties hy_prop_type = determine_hy_prop_type(aperture, transmissivity, permeability) fracture_dictionary['aperture'] = [aperture] fracture_dictionary['transmissivity'] = [transmissivity] fracture_dictionary['permeability'] = [permeability] fracture_dictionary['hy_prop_type'] = hy_prop_type ## Logic for i/o if shape == 'rect': self.params['userRectanglesOnOff']['value'] = True self.params['UserRect_Input_File_Path']['value'] = fracture_dictionary[ 'filename'] self.user_rect_params.append(fracture_dictionary) frac_number = len(self.user_rect_params) self.print_user_fracture_information('rect', frac_number - 1) elif shape == 'ell': if number_of_vertices > 2: fracture_dictionary['Number_of_Vertices:'] = number_of_vertices else: print_error( f"Error. number_of_vertices must be greater than 2. VAlue provided: {number_of_vertices}. Exiting." ) self.params['userEllipsesOnOff']['value'] = True self.params['UserEll_Input_File_Path']['value'] = fracture_dictionary[ 'filename'] self.user_ell_params.append(fracture_dictionary) frac_number = len(self.user_ell_params) self.print_user_fracture_information('ell', frac_number - 1)
def write_user_fractures_to_file(self): """Writes the user defined fracutres to a file if file is not already specified Parameters ------------ self : DFN object Returns --------- None Notes ------- None """ n_rects = len(self.user_rect_params) n_ells = len(self.user_ell_params) if n_ells > 0: print( f"--> Writing user defined ellispes to file {self.params['UserEll_Input_File_Path']['value']}" ) with open(self.params['UserEll_Input_File_Path']['value'], 'w+') as ell_file: ell_file.write(f'nUserEll: {n_ells} \n \n') orientation_option = self.user_ell_params[0][ 'userOrientationOption:'] for key in self.user_ell_params[0].keys(): if key == 'userOrientationOption:': value = self.user_ell_params[0][key] ell_file.write(f'{key} {value} \n \n') elif key == 'Normal:': if orientation_option == 0: ell_file.write(f'{key} \n') for j in range(n_ells): value = self.user_ell_params[j][key] if value is not None: ell_file.write(f'{value} \n') else: error = "user orientation option not specified correctly \n0:'normal'\n1:'trend_plunge'\n2:'dip_strike'\n" sys.stderr.write(error) sys.exit(1) ell_file.write('\n') else: continue elif key == 'Trend_Plunge:': if orientation_option == 1: ell_file.write(f'{key} \n') for j in range(n_ells): value = self.user_ell_params[j][key] if value is not None: ell_file.write(f'{value} \n') else: error = "user orientation option not specified correctly \n0:'normal'\n1:'trend_plunge'\n2:'dip_strike'\n" sys.stderr.write(error) sys.exit(1) ell_file.write('\n') else: continue elif key == 'Dip_Strike:': if orientation_option == 2: ell_file.write(f'{key} \n') for j in range(n_ells): value = self.user_ell_params[j][key] if value is not None: ell_file.write(f'{value} \n') else: error = "user orientation option not specified correctly \n0:'normal'\n1:'trend_plunge'\n2:'dip_strike'\n" sys.stderr.write(error) sys.exit(1) ell_file.write('\n') else: continue elif key == 'filename' or key == 'shape': continue else: ell_file.write(f'{key} \n') for j in range(n_ells): value = self.user_ell_params[j][key] ell_file.write(f'{value} \n') ell_file.write('\n') if n_rects > 0: print( f"--> Writing user defined rectangles to file {self.params['UserRect_Input_File_Path']['value']}" ) with open(self.params['UserRect_Input_File_Path']['value'], 'w+') as rect_file: rect_file.write(f'nUserRect: {n_rects} \n \n') orientation_option = self.user_rect_params[0][ 'userOrientationOption:'] for key in self.user_rect_params[0].keys(): if key == 'userOrientationOption:': value = self.user_rect_params[0][key] rect_file.write(f'{key} {value} \n \n') elif key == 'Normal:': if orientation_option == 0: rect_file.write(f'{key} \n') for j in range(n_rects): value = self.user_rect_params[j][key] if value is not None: rect_file.write(f'{value} \n') else: error = "user orientation option not specified correctly \n0:'Normal'\n1:'Trend_Plunge'\n2:Dip_Strike'" sys.stderr.write(error) sys.exit(1) rect_file.write('\n') else: continue elif key == 'Trend_Plunge:': if orientation_option == 1: rect_file.write(f'{key} \n') for j in range(n_rects): value = self.user_rect_params[j][key] if value is not None: rect_file.write(f'{value} \n') else: error = "user orientation option not specified correctly \n0:'Normal'\n1:'Trend_Plunge'\n2:Dip_Strike'" sys.stderr.write(error) sys.exit(1) rect_file.write('\n') else: continue elif key == 'Dip_Strike:': if orientation_option == 2: rect_file.write(f'{key} \n') for j in range(n_rects): value = self.user_rect_params[j][key] if value is not None: rect_file.write(f'{value} \n') else: error = "user orientation option not specified correctly \n0:'Normal'\n1:'Trend_Plunge'\n2:Dip_Strike'" sys.stderr.write(error) sys.exit(1) rect_file.write('\n') else: continue elif key == 'filename': continue elif key == 'shape': continue else: rect_file.write(f'{key} \n') for j in range(n_rects): value = self.user_rect_params[j][key] rect_file.write(f'{value} \n') rect_file.write('\n') def determine_hy_prop_type(aperture, transmissivity, permeability): """Determines the type of user defined hydraulic property based on user inupt Parameters ------------- aperture : None or Float transmissivity : None or Float permeability : None or Float Returns --------- The hydraulic property type. Exactly one of the three parameters must be a float or an exception will be thrown Notes -------""" #Determine Hydraulic Property type hy_prop_type = None if aperture is not None: hy_prop_type = 'aperture' if transmissivity is not None: if hy_prop_type != None: error = "\nPlease specify exactly one of the following for user defined fracture: aperture, transmissivity, permeability\n" sys.stderr.write(error) sys.exit(1) else: hy_prop_type = 'transmissivity' if permeability is not None: if hy_prop_type != None: error = "\nPlease specify exactly one of the following for user defined fracture: aperture, transmissivity, permeability\n" sys.stderr.write(error) sys.exit(1) else: hy_prop_type = 'permeability' if hy_prop_type == None: error = "\nPlease specify exactly one of the following for user defined fracture: aperture, transmissivity, permeability\n" sys.stderr.write(error) sys.exit(1) return hy_prop_type