示例#1
0
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
示例#2
0
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