def _assemble_in_bucket(grids, **kwargs): """ Create a GridBucket from a list of grids. Parameters ---------- grids: A list of lists of grids. Each element in the list is a list of all grids of a the same dimension. It is assumed that the grids are sorted from high dimensional grids to low dimensional grids. All grids must also have the mapping g.global_point_ind which maps the local nodes of the grid to the nodes of the highest dimensional grid. Returns ------- GridBucket: A GridBucket class where the mapping face_cells are given to each edge. face_cells maps from lower-dim cells to higher-dim faces. """ # Create bucket bucket = GridBucket() [bucket.add_nodes(g_d) for g_d in grids] # We now find the face_cell mapings. for dim in range(len(grids) - 1): for hg in grids[dim]: # We have to specify the number of nodes per face to generate a # matrix of the nodes of each face. n_per_face = _nodes_per_face(hg) fn_loc = hg.face_nodes.indices.reshape( (n_per_face, hg.num_faces), order="F" ) # Convert to global numbering fn = hg.global_point_ind[fn_loc] fn = np.sort(fn, axis=0) for lg in grids[dim + 1]: cell_2_face, cell = tools.obtain_interdim_mappings( lg, fn, n_per_face, **kwargs ) if cell_2_face.size > 0: face_cells = sps.csc_matrix( (np.ones(cell.size, dtype=bool), (cell, cell_2_face)), (lg.num_cells, hg.num_faces), ) bucket.add_edge([hg, lg], face_cells) return bucket
def update_nodes( g, g_1d, new_grid_1d, this_in_combined, sort_ind, global_ind_offset, list_of_grids ): """Update a 2d grid to conform to a new grid along a 1d line. Intended use: A 1d mesh that is embedded in a 2d mesh (along a fracture) has been updated / refined. This function then updates the node information in the 2d grid. Parameters: g (grid, dim==2): Main grid to update. Has faces along a fracture. g_1d (grid, dim==1): Original line grid along the fracture. new_grid_1d (grid, dim==1): New line grid, formed by merging two coinciding, but non-matching grids along a fracture. this_in_combined (np.ndarray): Which nodes in the new grid are also in the old one, as returned by merge_1d_grids(). sort_ind (np.ndarray): Sorting indices of the coordinates of the old grid, as returned by merge_1d_grids(). list_of_grids (list): Grids for all dimensions. Returns: """ nodes_per_face = 2 # Face-node relation for the grid, in terms of local and global indices fn = g.face_nodes.indices.reshape((nodes_per_face, g.num_faces), order="F") fn_glob = np.sort(g.global_point_ind[fn], axis=0) # Mappings between faces in 2d grid and cells in 1d # 2d faces along the 1d grid will be deleted. delete_faces, cell_1d = fractools.obtain_interdim_mappings( g_1d, fn_glob, nodes_per_face ) # All 1d cells should be identified with 2d faces assert ( cell_1d.size == g_1d.num_cells ), """ Failed to find mapping between 1d cells and 2d faces""" # The nodes of identified faces on the 2d grid will be deleted delete_nodes = np.unique(fn[:, delete_faces]) # Nodes to be added will have indicies towards the end num_nodes_orig = g.num_nodes num_delete_nodes = delete_nodes.size # Define indices of new nodes. new_nodes = num_nodes_orig - delete_nodes.size + np.arange(new_grid_1d.num_nodes) # Adjust node indices in the face-node relation # First, map nodes between 1d and 2d grids. Use sort_ind here to map # indices of g_1d to the same order as the new grid _, node_map_1d_2d = ismember_rows( g.global_point_ind[delete_nodes], g_1d.global_point_ind ) tmp = np.arange(g.num_nodes) adjustment = np.zeros_like(tmp) adjustment[delete_nodes] = 1 node_adjustment = tmp - np.cumsum(adjustment) # Nodes along the 1d grid are deleted and inserted again. Let the # adjutsment point to the restored nodes. # node_map_1d_2d maps from ordering in delete_nodes to ordering of 1d # points (old_grid). this_in_combined then maps further to the ordering of # the new 1d grid node_adjustment[delete_nodes] = ( g.num_nodes - num_delete_nodes + this_in_combined[node_map_1d_2d] ) g.face_nodes.indices = node_adjustment[g.face_nodes.indices] # Update node coordinates and global indices for 2d mesh g.nodes = np.hstack((g.nodes, new_grid_1d.nodes)) new_global_points = new_grid_1d.global_point_ind g.global_point_ind = np.append(g.global_point_ind, new_global_points) # Global index of deleted points old_global_pts = g.global_point_ind[delete_nodes] # Update any occurences of the old points in other grids. When sewing # together a DFN grid, this may involve more and more updates as common # nodes are found along intersections. # The new grid should also be added to the list, if it is not there before if new_grid_1d not in list_of_grids: list_of_grids.append(new_grid_1d) update_global_point_ind( list_of_grids, old_global_pts, new_global_points[this_in_combined[node_map_1d_2d]], ) # Delete old nodes g.nodes = np.delete(g.nodes, delete_nodes, axis=1) g.global_point_ind = np.delete(g.global_point_ind, delete_nodes) g.num_nodes = g.nodes.shape[1] return new_nodes, delete_faces, global_ind_offset