Source code for darts.models.reservoirs.unstruct_reservoir



[docs] class UnstructReservoir:
[docs] def calc_boundary_cells(self, boundary_data): """ Class method which calculates constant boundary values at a specif constant x,y,z-coordinate :param boundary_data: dictionary with the boundary location (X,Y,Z, and location) :return: """ # Specify boundary cells, simply set specify the single coordinate which is not-changing and its value: # First boundary: index = [] # Dynamic list containing indices of the nodes (points) which lay on the boundary: if boundary_data['first_boundary_dir'] == 'X': # Check if first coordinate of points is on the boundary: index = self.unstr_discr.mesh_data.points[:, 0] == boundary_data['first_boundary_val'] elif boundary_data['first_boundary_dir'] == 'Y': # Check if first coordinate of points is on the boundary: index = self.unstr_discr.mesh_data.points[:, 1] == boundary_data['first_boundary_val'] elif boundary_data['first_boundary_dir'] == 'Z': # Check if first coordinate of points is on the boundary: index = self.unstr_discr.mesh_data.points[:, 2] == boundary_data['first_boundary_val'] # Convert dynamic list to numpy array: left_boundary_points = np.array(list(compress(range(len(index)), index))) # Second boundary (same as above): index = [] if boundary_data['second_boundary_dir'] == 'X': # Check if first coordinate of points is on the boundary: index = self.unstr_discr.mesh_data.points[:, 0] == boundary_data['second_boundary_val'] elif boundary_data['second_boundary_dir'] == 'Y': # Check if first coordinate of points is on the boundary: index = self.unstr_discr.mesh_data.points[:, 1] == boundary_data['second_boundary_val'] elif boundary_data['second_boundary_dir'] == 'Z': # Check if first coordinate of points is on the boundary: index = self.unstr_discr.mesh_data.points[:, 2] == boundary_data['second_boundary_val'] right_boundary_points = np.array(list(compress(range(len(index)), index))) # Find cells containing boundary cells, for wedges or hexahedrons, the boundary cells must contain, # on the X or Y boundary four nodes exactly! # 0------0 0 # / / | / \ # 0------0 0 0----0 # | | / | | # 0------0 0----0 # Hexahedron Wedge (prism) # Create loop over all matrix cells which are of the geometry 'matrix_cell_type' left_count = 0 # Counter for number of left matrix cells on the boundary left_boundary_cells = {} # Dictionary with matrix cells on the left boundary for geometry in self.unstr_discr.geometries_in_mesh_file: if geometry in self.unstr_discr.available_matrix_geometries: # Matrix geometry found, check if any matrix control volume has exactly 4 nodes which intersect with # the left_boundary_points list: for ith_cell, ith_row in enumerate( self.unstr_discr.mesh_data.cells_dict[geometry]): if len(set.intersection(set(ith_row), set(left_boundary_points))) == 4: # Store cell since it is on the left boundary: left_boundary_cells[left_count] = ith_cell left_count += 1 right_count = 0 right_boundary_cells = {} for geometry in self.unstr_discr.geometries_in_mesh_file: if geometry in self.unstr_discr.available_matrix_geometries: # Matrix geometry found, check if any matrix control volume has exactly 4 nodes which intersect with # the right_boundary_points list: for ith_cell, ith_row in enumerate( self.unstr_discr.mesh_data.cells_dict[geometry]): if len(set.intersection(set(ith_row), set(right_boundary_points))) == 4: # Store cell since it is on the left boundary: right_boundary_cells[right_count] = ith_cell right_count += 1 self.left_boundary_cells = np.array(list(left_boundary_cells.values()), dtype=int) + \ self.unstr_discr.fracture_cell_count self.right_boundary_cells = np.array(list(right_boundary_cells.values()), dtype=int) + \ self.unstr_discr.fracture_cell_count return 0
[docs] def add_well(self, name, depth): """ Class method which adds wells heads to the reservoir (Note: well head is not equal to a perforation!) :param name: :param depth: :return: """ well = ms_well() well.name = name well.segment_volume = 0.0785 * 40 # 2.5 * pi * 0.15**2 / 4 well.well_head_depth = depth well.well_body_depth = depth well.segment_transmissibility = 1e5 well.segment_depth_increment = 1 self.wells.append(well) return 0
[docs] def add_perforation(self, well, res_block, well_index=-1, well_indexD=-1, well_radius=0.1524, skin=0., multi_segment=True, verbose=False): """ Class method which ads perforation to each (existing!) well :param well: data object which contains data of the particular well :param res_block: reservoir block in which the well has a perforation :param well_index: well index (productivity index) :return: """ # calculate well index and get local index of reservoir block wi, wid = self.unstr_discr.calc_equivalent_well_index(res_block, well_radius=well_radius, skin=skin) if well_index == -1: well_index = wi if well_indexD == -1: well_indexD = wid # set well segment index (well block) equal to index of perforation layer if multi_segment: well_block = len(well.perforations) else: well_block = 0 well.perforations = well.perforations + [(well_block, res_block, well_index, well_indexD)] if verbose: print('Added perforation for well %s to block %d with WI=%f' % (well.name, res_block, well_index)) return 0