Пример #1
0
    def get_ppt(self,ppt_nx,ppt_ny,ppt_dz,zone_array,ppt_name_root='pt',param_name_root='k_',ipar_init=1):
        '''Generates a dataframe of pilot point locations. Note that grid_util.globalxy_to_localxy
        uses the northwest corner of the model grid as the origin.  However, the PEST 
        pilot points file assumes the SW corner of the model grid as the origin (i.e., 
        it prints coordinates as northings and eastings.)'''

        # Generate the pilot point grid in the row/col plane
        x_vector = np.linspace(0,self.delr * self.ncol,ppt_nx+1)[:-1]
        x_vector = np.add(x_vector,0.5*(x_vector[1]-x_vector[0]))
        
        y_vector = np.linspace(0,self.delc * self.nrow,ppt_ny+1)[:-1]
        y_vector = np.add(y_vector,0.5*(y_vector[1]-y_vector[0]))
        
        ppt_df = pd.DataFrame(columns=['PPT_Name','Param_Name','Easting','Northing','Elevation','Zone','Value'])
        icount = 0
        
        for ix,jy in product(x_vector,y_vector):
            
            # row and column returned from this function in PYTHON indexing
            irow,icol,_,_ = gu.modelxy_to_rowcol(ix,(self.nrow*self.delc - jy),self.delr,self.delc)
        
            # Generate the vertical dimension of the pilot point grid
            # This algorithm assumes that for any (row,col), no active cells are found
            # beneath any inactive cells.
            z_0 = self.midpoints[irow,icol][0]
            z_vector = np.arange(z_0,z_0 - np.sum(self.layer_depths),-(abs(ppt_dz)))
            
            # The PEST 10-character limit precludes
            # writing row,col, and layer identifiers into the pilot point name.
            # As an alternative, I've simply labeled them A,B,C, etc., starting
            # with the top pilot point in a given (row,col)
            for iz,iletter in zip(z_vector,string.uppercase[:(len(z_vector))]):
    
                ilay,_ = gu.globalz_to_localz(irow,icol,iz,self.midpoints,self.bottoms,self.layer_depths)
                if (gu.check_if_active(irow,icol,ilay,self.ibound) == True):
                    
                    izone = zone_array[irow-1,icol-1,ilay-1]
                    ppt_name = ppt_name_root + str(irow) + '_' + str(icol) + iletter
                    param_name = param_name_root + str(irow) + '_' + str(icol) + iletter
                    
                    ppt_df.loc[icount,:] = [ppt_name,param_name,ix,jy,iz,izone,ipar_init]
                    icount += 1
        
        return ppt_df
Пример #2
0
    def get_ppt(self,
                ppt_nx,
                ppt_ny,
                ppt_dz,
                zone_array,
                ppt_name_root='pt',
                param_name_root='k_',
                ipar_init=1):
        '''Generates a dataframe of pilot point locations. Note that grid_util.globalxy_to_localxy
        uses the northwest corner of the model grid as the origin.  However, the PEST 
        pilot points file assumes the SW corner of the model grid as the origin (i.e., 
        it prints coordinates as northings and eastings.)'''

        # Generate the pilot point grid in the row/col plane
        x_vector = np.linspace(0, self.delr * self.ncol, ppt_nx + 1)[:-1]
        x_vector = np.add(x_vector, 0.5 * (x_vector[1] - x_vector[0]))

        y_vector = np.linspace(0, self.delc * self.nrow, ppt_ny + 1)[:-1]
        y_vector = np.add(y_vector, 0.5 * (y_vector[1] - y_vector[0]))

        ppt_df = pd.DataFrame(columns=[
            'PPT_Name', 'Param_Name', 'Easting', 'Northing', 'Elevation',
            'Zone', 'Value'
        ])
        icount = 0

        for ix, jy in product(x_vector, y_vector):

            # row and column returned from this function in PYTHON indexing
            irow, icol, _, _ = gu.modelxy_to_rowcol(
                ix, (self.nrow * self.delc - jy), self.delr, self.delc)

            # Generate the vertical dimension of the pilot point grid
            # This algorithm assumes that for any (row,col), no active cells are found
            # beneath any inactive cells.
            z_0 = self.midpoints[irow, icol][0]
            z_vector = np.arange(z_0, z_0 - np.sum(self.layer_depths),
                                 -(abs(ppt_dz)))

            # The PEST 10-character limit precludes
            # writing row,col, and layer identifiers into the pilot point name.
            # As an alternative, I've simply labeled them A,B,C, etc., starting
            # with the top pilot point in a given (row,col)
            for iz, iletter in zip(z_vector,
                                   string.uppercase[:(len(z_vector))]):

                ilay, _ = gu.globalz_to_localz(irow, icol, iz, self.midpoints,
                                               self.bottoms, self.layer_depths)
                if (gu.check_if_active(irow, icol, ilay, self.ibound) == True):

                    izone = zone_array[irow - 1, icol - 1, ilay - 1]
                    ppt_name = ppt_name_root + str(irow) + '_' + str(
                        icol) + iletter
                    param_name = param_name_root + str(irow) + '_' + str(
                        icol) + iletter

                    ppt_df.loc[icount, :] = [
                        ppt_name, param_name, ix, jy, iz, izone, ipar_init
                    ]
                    icount += 1

        return ppt_df
Пример #3
0
def get_well_startloc(start_df,top=None,bottoms=None,midpoints=None,min_particle_separation=1,\
                      reg_cylinder=None,particles_per_cell=None,delr=None,delc=None,lay_thick=None):
    '''Returns a dictionary of particle starting locations for input to MODPATH
    package writing functions. Removes duplicate station LOCATIONS from
    the dataframe that may include multiple observations at a particular station.
    If the specs for a registration volume are provided,
    distributes particles throughout the registration volume.  If no registration
    volume is provided, distributes particles in well screen.  (NOTE: Function
    currently only allows generation of a registration CYLINDER.) Returns PYTHON
    indexing.'''

    nlay, nrow, ncol = np.shape(bottoms)

    start_df = start_df.reset_index()
    start_df = start_df.drop_duplicates('index').set_index('index')
    start_df.index.names = ['station_nm']
    start_df = start_df.drop(['ObsName', 'TobDate'], axis=1)

    # If the dimensions of a registration cylinder are provided, generate a
    # vogel disc in order to determine the distance between points.  This will
    # be used to assign the number of vertical increments to the registration
    # cylinder.  Otherwise (i.e., for cases in which particles are only generated
    # from the well screen), use the min_particle_separation parameter to vertically
    # discretize the well screen.
    if (reg_cylinder is not None):
        iradius, dz_top, dz_bottom = reg_cylinder['Radius'], reg_cylinder[
            'Top'], reg_cylinder['Bottom']
        particles_per_disc = get_disc_particles(iradius, particles_per_cell,
                                                delr, delc)
        points_xy = vogel_disc((0, 0), particles_per_disc, iradius)
        distance_between_points = np.max(
            [dist_bt_points(points_xy), min_particle_separation])

    else:
        distance_between_points = min_particle_separation
        dz_top, dz_bottom = 0, 0

    # Loop through all the observation locations
    particle_start_dict = dict()
    for iname, irow in start_df.iterrows():

        print 'Generating particle starting locations for %s.' % (iname)

        # Read the well location from the dataframe
        x0, y0, ztop, zbottom = irow['ModelX'], irow['ModelY'], irow[
            'GlobZtop'], irow['GlobZbot']

        # Update the upper and lower bounds on the starting particle locations
        ztop = ztop + dz_top
        zbottom = zbottom - dz_bottom
        nz_increments = int(np.ceil(
            (ztop - zbottom) / distance_between_points))

        # Distribute the particles throughout the well screen or the associated
        # registration volume. 'vert_particle_line' is a vector of elevations
        # at which the particles are set
        if (reg_cylinder is not None):
            if (nrow == 1
                ):  # For 2D case generate a plane rather than a cylinder
                points_xy, vert_particle_line = points_on_plane(
                    (x0, y0), iradius, ztop, zbottom, particles_per_cell, delc,
                    lay_thick)
            else:
                points_xy = vogel_disc((x0, y0), particles_per_disc, iradius)
                vert_particle_line = np.linspace(zbottom,
                                                 ztop,
                                                 num=nz_increments)

        else:  # Only generate particles within the well screen
            points_xy = [(x0, y0)]
            vert_particle_line = np.linspace(zbottom, ztop, num=nz_increments)

        # Convert the global elevations to layer number with localz
        for ivert in vert_particle_line:

            for ipoint in points_xy:

                xx, yy = ipoint[0], ipoint[1]
                irow, jcol, local_x, local_y = gu.modelxy_to_localxy(
                    xx, yy, delr, delc, nrow, ncol)

                # Do not place particles above the model top or below the model bottom
                if (ivert > top[irow, jcol]) or (ivert < bottoms[-1, irow,
                                                                 jcol]):
                    break

                ilay, local_z = gu.globalz_to_localz(irow, jcol, ivert,
                                                     midpoints, bottoms,
                                                     lay_thick)

                if iname not in particle_start_dict:
                    particle_start_dict[iname] = [(ilay, irow, jcol, local_x,
                                                   local_y, local_z)]
                else:
                    particle_start_dict[iname].append(
                        (ilay, irow, jcol, local_x, local_y, local_z))

    return particle_start_dict
Пример #4
0
def get_well_startloc(
    start_df,
    top=None,
    bottoms=None,
    midpoints=None,
    min_particle_separation=1,
    reg_cylinder=None,
    particles_per_cell=None,
    delr=None,
    delc=None,
    lay_thick=None,
):
    """Returns a dictionary of particle starting locations for input to MODPATH
    package writing functions. Removes duplicate station LOCATIONS from
    the dataframe that may include multiple observations at a particular station.
    If the specs for a registration volume are provided,
    distributes particles throughout the registration volume.  If no registration
    volume is provided, distributes particles in well screen.  (NOTE: Function
    currently only allows generation of a registration CYLINDER.) Returns PYTHON
    indexing."""

    nlay, nrow, ncol = np.shape(bottoms)

    start_df = start_df.reset_index()
    start_df = start_df.drop_duplicates("index").set_index("index")
    start_df.index.names = ["station_nm"]
    start_df = start_df.drop(["ObsName", "TobDate"], axis=1)

    # If the dimensions of a registration cylinder are provided, generate a
    # vogel disc in order to determine the distance between points.  This will
    # be used to assign the number of vertical increments to the registration
    # cylinder.  Otherwise (i.e., for cases in which particles are only generated
    # from the well screen), use the min_particle_separation parameter to vertically
    # discretize the well screen.
    if reg_cylinder is not None:
        iradius, dz_top, dz_bottom = reg_cylinder["Radius"], reg_cylinder["Top"], reg_cylinder["Bottom"]
        particles_per_disc = get_disc_particles(iradius, particles_per_cell, delr, delc)
        points_xy = vogel_disc((0, 0), particles_per_disc, iradius)
        distance_between_points = np.max([dist_bt_points(points_xy), min_particle_separation])

    else:
        distance_between_points = min_particle_separation
        dz_top, dz_bottom = 0, 0

    # Loop through all the observation locations
    particle_start_dict = dict()
    for iname, irow in start_df.iterrows():

        print "Generating particle starting locations for %s." % (iname)

        # Read the well location from the dataframe
        x0, y0, ztop, zbottom = irow["ModelX"], irow["ModelY"], irow["GlobZtop"], irow["GlobZbot"]

        # Update the upper and lower bounds on the starting particle locations
        ztop = ztop + dz_top
        zbottom = zbottom - dz_bottom
        nz_increments = int(np.ceil((ztop - zbottom) / distance_between_points))

        # Distribute the particles throughout the well screen or the associated
        # registration volume. 'vert_particle_line' is a vector of elevations
        # at which the particles are set
        if reg_cylinder is not None:
            if nrow == 1:  # For 2D case generate a plane rather than a cylinder
                points_xy, vert_particle_line = points_on_plane(
                    (x0, y0), iradius, ztop, zbottom, particles_per_cell, delc, lay_thick
                )
            else:
                points_xy = vogel_disc((x0, y0), particles_per_disc, iradius)
                vert_particle_line = np.linspace(zbottom, ztop, num=nz_increments)

        else:  # Only generate particles within the well screen
            points_xy = [(x0, y0)]
            vert_particle_line = np.linspace(zbottom, ztop, num=nz_increments)

        # Convert the global elevations to layer number with localz
        for ivert in vert_particle_line:

            for ipoint in points_xy:

                xx, yy = ipoint[0], ipoint[1]
                irow, jcol, local_x, local_y = gu.modelxy_to_localxy(xx, yy, delr, delc, nrow, ncol)

                # Do not place particles above the model top or below the model bottom
                if (ivert > top[irow, jcol]) or (ivert < bottoms[-1, irow, jcol]):
                    break

                ilay, local_z = gu.globalz_to_localz(irow, jcol, ivert, midpoints, bottoms, lay_thick)

                if iname not in particle_start_dict:
                    particle_start_dict[iname] = [(ilay, irow, jcol, local_x, local_y, local_z)]
                else:
                    particle_start_dict[iname].append((ilay, irow, jcol, local_x, local_y, local_z))

    return particle_start_dict