Exemple #1
0
def update_face_tags(g, delete_faces, new_faces):
    """Update the face tags of a cell.

    Delete tags for old faces, and add new tags for their replacements.

    If the grid has no face tags, no change is done

    Parameters:
        g (grid): To be modified
        delete_faces (np.array or list): Faces to be deleted.
        new_faces (list of list): For each item in delete_faces, a list of new
            replacement faces.

    """
    keys = tags.standard_face_tags()
    for key in keys:
        if hasattr(g, "tags"):
            old_tags = g.tags[key].copy()
            old_tags = np.delete(old_tags, delete_faces)
            num_new = np.array([len(new_faces[i]) for i in range(len(new_faces))])
            new_tags = np.zeros(num_new.sum(), dtype=bool)
            divides = np.hstack((0, np.cumsum(num_new)))
            for i, d in enumerate(delete_faces):
                new_tags[divides[i] : divides[i + 1]] = g.tags[key][d]
            g.tags[key] = np.hstack((old_tags, new_tags))
Exemple #2
0
def remove_faces(g, face_id, rem_cell_faces=True):
    """
    Remove faces from grid.

    PARAMETERS:
    -----------
    g              - A grid
    face_id        - Indices of faces to remove
    rem_cell_faces - Defaults to True. If set to false, the g.cell_faces matrix
                     is not changed.
    """
    # update face info
    keep = np.array([True] * g.num_faces)
    keep[face_id] = False
    g.face_nodes = g.face_nodes[:, keep]
    g.num_faces -= face_id.size
    g.face_normals = g.face_normals[:, keep]
    g.face_areas = g.face_areas[keep]
    g.face_centers = g.face_centers[:, keep]
    # Not sure if still works
    for key in tags.standard_face_tags():
        g.tags[key] = g.tags[key][keep]

    if rem_cell_faces:
        g.cell_faces = g.cell_faces[keep, :]
Exemple #3
0
    def _check_tags(self) -> None:
        for key in tags.standard_node_tags():
            if key not in self.tags.keys():
                raise ValueError(f"The tag key {key} must be specified")
            value = self.tags.get(key)
            if not value.size == self.num_nodes:
                raise ValueError(f"Wrong size of value for tag {key}")

        for key in tags.standard_face_tags():
            if key not in self.tags.keys():
                raise ValueError(f"The tag key {key} must be specified")
            value = self.tags.get(key)
            if not value.size == self.num_faces:
                raise ValueError(f"Wrong size of value for tag {key}")
Exemple #4
0
 def initiate_face_tags(self) -> None:
     keys = tags.standard_face_tags()
     values = [np.zeros(self.num_faces, dtype=bool) for _ in keys]
     tags.add_tags(self, dict(zip(keys, values)))
Exemple #5
0
def generate_coarse_grid_single(g, subdiv, face_map):
    """
    Specific function for a single grid. Use the common interface instead.
    """

    subdiv = np.asarray(subdiv)
    assert subdiv.size == g.num_cells

    # declare the storage array to build the cell_faces map
    cell_faces = np.empty(0, dtype=g.cell_faces.indptr.dtype)
    cells = np.empty(0, dtype=cell_faces.dtype)
    orient = np.empty(0, dtype=g.cell_faces.data.dtype)

    # declare the storage array to build the face_nodes map
    face_nodes = np.empty(0, dtype=g.face_nodes.indptr.dtype)
    nodes = np.empty(0, dtype=face_nodes.dtype)
    visit = np.zeros(g.num_faces, dtype=np.bool)

    # compute the face_node indexes
    num_nodes_per_face = g.face_nodes.indptr[1:] - g.face_nodes.indptr[:-1]
    face_node_ind = matrix_compression.rldecode(np.arange(g.num_faces),
                                                num_nodes_per_face)

    cells_list = np.unique(subdiv)
    cell_volumes = np.zeros(cells_list.size)
    cell_centers = np.zeros((3, cells_list.size))

    for cellId, cell in enumerate(cells_list):
        # extract the cells of the original mesh associated to a specific label
        cells_old = np.where(subdiv == cell)[0]

        # compute the volume
        cell_volumes[cellId] = np.sum(g.cell_volumes[cells_old])
        cell_centers[:, cellId] = np.average(g.cell_centers[:, cells_old],
                                             axis=1)

        # reconstruct the cell_faces mapping
        faces_old, _, orient_old = sps.find(g.cell_faces[:, cells_old])
        mask = np.ones(faces_old.size, dtype=np.bool)
        mask[np.unique(faces_old, return_index=True)[1]] = False
        # extract the indexes of the internal edges, to be discared
        index = np.array(
            [np.where(faces_old == f)[0] for f in faces_old[mask]],
            dtype=np.int).ravel()
        faces_new = np.delete(faces_old, index)
        cell_faces = np.r_[cell_faces, faces_new]
        cells = np.r_[cells, np.repeat(cellId, faces_new.shape[0])]
        orient = np.r_[orient, np.delete(orient_old, index)]

        # reconstruct the face_nodes mapping
        # consider only the unvisited faces
        not_visit = ~visit[faces_new]
        if not_visit.size == 0 or np.all(~not_visit):
            continue
        # mask to consider only the external faces
        mask = np.atleast_1d(
            np.sum(
                [face_node_ind == f for f in faces_new[not_visit]],
                axis=0,
                dtype=np.bool,
            ))
        face_nodes = np.r_[face_nodes, face_node_ind[mask]]

        nodes_new = g.face_nodes.indices[mask]
        nodes = np.r_[nodes, nodes_new]
        visit[faces_new] = True

    # Rename the faces
    cell_faces_unique = np.unique(cell_faces)
    cell_faces_id = np.arange(cell_faces_unique.size, dtype=cell_faces.dtype)
    cell_faces = np.array([
        cell_faces_id[np.where(cell_faces_unique == f)[0]] for f in cell_faces
    ]).ravel()
    shape = (cell_faces_unique.size, cells_list.size)
    cell_faces = sps.csc_matrix((orient, (cell_faces, cells)), shape=shape)

    # Rename the nodes
    face_nodes = np.array([
        cell_faces_id[np.where(cell_faces_unique == f)[0]] for f in face_nodes
    ]).ravel()
    nodes_list = np.unique(nodes)
    nodes_id = np.arange(nodes_list.size, dtype=nodes.dtype)
    nodes = np.array([nodes_id[np.where(nodes_list == n)[0]]
                      for n in nodes]).ravel()

    # sort the nodes
    nodes = nodes[np.argsort(face_nodes, kind="mergesort")]
    data = np.ones(nodes.size, dtype=g.face_nodes.data.dtype)
    indptr = np.r_[0, np.cumsum(np.bincount(face_nodes))]
    face_nodes = sps.csc_matrix((data, nodes, indptr))

    # store again the data in the same grid
    g.name.append("coarse")

    g.nodes = g.nodes[:, nodes_list]
    g.num_nodes = g.nodes.shape[1]

    g.face_nodes = face_nodes
    g.num_faces = g.face_nodes.shape[1]
    g.face_areas = g.face_areas[cell_faces_unique]
    g.tags = tags.extract(g.tags, cell_faces_unique, tags.standard_face_tags())
    g.face_normals = g.face_normals[:, cell_faces_unique]
    g.face_centers = g.face_centers[:, cell_faces_unique]

    g.cell_faces = cell_faces
    g.num_cells = g.cell_faces.shape[1]
    g.cell_volumes = cell_volumes
    g.cell_centers = half_space.star_shape_cell_centers(g)
    is_nan = np.isnan(g.cell_centers[0, :])
    g.cell_centers[:, is_nan] = cell_centers[:, is_nan]

    if face_map:
        return np.array([cell_faces_unique, cell_faces_id])
Exemple #6
0
 def initiate_face_tags(self):
     keys = tags.standard_face_tags()
     values = [
         np.zeros(self.num_faces, dtype=bool) for _ in range(len(keys))
     ]
     tags.add_tags(self, dict(zip(keys, values)))
Exemple #7
0
def duplicate_faces(gh, face_cells):
    """
    Duplicate all faces that are connected to a lower-dim cell

    Parameters
    ----------
    gh         - Higher-dim grid
    face_cells - A list of connection matrices. Each matrix gives
                 the mapping from the cells of a lower-dim grid
                 to the faces of the higher diim grid.
    """
    # We find the indices of the higher-dim faces to be duplicated.
    # Each of these faces are duplicated, and the duplication is
    # attached to the same nodes. We do not attach the faces to
    # any cells as this connection will have to be undone later
    # anyway.
    frac_id = face_cells.nonzero()[1]
    frac_id = np.unique(frac_id)
    rem = tags.all_face_tags(gh.tags)[frac_id]
    gh.tags["fracture_faces"][frac_id[rem]] = True
    gh.tags["tip_faces"][frac_id] = False

    frac_id = frac_id[~rem]
    if frac_id.size == 0:
        return frac_id

    node_start = gh.face_nodes.indptr[frac_id]
    node_end = gh.face_nodes.indptr[frac_id + 1]
    nodes = gh.face_nodes.indices[mcolon(node_start, node_end)]
    added_node_pos = np.cumsum(node_end -
                               node_start) + gh.face_nodes.indptr[-1]
    assert added_node_pos.size == frac_id.size
    assert added_node_pos[-1] - gh.face_nodes.indptr[-1] == nodes.size
    gh.face_nodes.indices = np.hstack((gh.face_nodes.indices, nodes))
    gh.face_nodes.indptr = np.hstack((gh.face_nodes.indptr, added_node_pos))
    gh.face_nodes.data = np.hstack(
        (gh.face_nodes.data, np.ones(nodes.size, dtype=bool)))
    gh.face_nodes._shape = (gh.num_nodes,
                            gh.face_nodes.shape[1] + frac_id.size)
    assert gh.face_nodes.indices.size == gh.face_nodes.indptr[-1]

    node_start = gh.face_nodes.indptr[frac_id]
    node_end = gh.face_nodes.indptr[frac_id + 1]

    # frac_nodes = gh.face_nodes[:, frac_id]

    # gh.face_nodes = sps.hstack((gh.face_nodes, frac_nodes))
    # We also copy the attributes of the original faces.
    gh.num_faces += frac_id.size
    gh.face_normals = np.hstack((gh.face_normals, gh.face_normals[:, frac_id]))
    gh.face_areas = np.append(gh.face_areas, gh.face_areas[frac_id])
    gh.face_centers = np.hstack((gh.face_centers, gh.face_centers[:, frac_id]))

    # Not sure if this still does the correct thing. Might have to
    # send in a logical array instead of frac_id.
    gh.tags["fracture_faces"][frac_id] = True
    gh.tags["tip_faces"][frac_id] = False
    update_fields = tags.standard_face_tags()
    update_values = [[]] * len(update_fields)
    for i, key in enumerate(update_fields):
        update_values[i] = gh.tags[key][frac_id]
    tags.append_tags(gh.tags, update_fields, update_values)

    return frac_id
Exemple #8
0
 def __init__(self, n_tags):
     keys = tags.standard_face_tags()
     values = [np.zeros(n_tags, dtype=bool) for _ in range(len(keys))]
     tags.add_tags(self, dict(zip(keys, values)))
def check_equivalent_buckets(buckets, decimals=12):
    """
    Checks agreement between number of cells, faces and nodes, their
    coordinates and the connectivity matrices cell_faces and face_nodes. Also
    checks the face tags.

    """
    dim_h = buckets[0].dim_max()
    dim_l = dim_h - 1
    num_buckets = len(buckets)
    cell_maps_h, face_maps_h = [], []
    cell_maps_l, face_maps_l = num_buckets * [{}], num_buckets * [{}]

    # Check that all buckets have the same number of grids in the lower dimension
    num_grids_l: int = len(buckets[0].grids_of_dimension(dim_h - 1))
    for bucket in buckets:
        assert len(bucket.grids_of_dimension(dim_h - 1)) == num_grids_l

    for d in range(dim_l, dim_h + 1):
        for target_grid in range(len(buckets[0].grids_of_dimension(d))):

            n_cells, n_faces, n_nodes = np.empty(0), np.empty(0), np.empty(0)
            nodes, face_centers, cell_centers = [], [], []
            cell_faces, face_nodes = [], []
            for bucket in buckets:
                g = bucket.grids_of_dimension(d)[target_grid]
                n_cells = np.append(n_cells, g.num_cells)
                n_faces = np.append(n_faces, g.num_faces)
                n_nodes = np.append(n_nodes, g.num_nodes)
                cell_faces.append(g.cell_faces)
                face_nodes.append(g.face_nodes)
                cell_centers.append(g.cell_centers)
                face_centers.append(g.face_centers)
                nodes.append(g.nodes)

            # Check that all buckets have the same number of cells, faces and nodes
            assert np.unique(n_cells).size == 1
            assert np.unique(n_faces).size == 1
            assert np.unique(n_nodes).size == 1

            # Check that the coordinates agree
            cell_centers = np.round(cell_centers, decimals)
            nodes = np.round(nodes, decimals)
            face_centers = np.round(face_centers, decimals)
            for i in range(1, num_buckets):
                assert np.all(
                    sm.ismember_rows(cell_centers[0], cell_centers[i])[0])
                assert np.all(
                    sm.ismember_rows(face_centers[0], face_centers[i])[0])
                assert np.all(sm.ismember_rows(nodes[0], nodes[i])[0])

            # Now we know all nodes, faces and cells are in all grids, we map them
            # to prepare cell_faces and face_nodes comparison
            g_0 = buckets[0].grids_of_dimension(d)[target_grid]
            for i in range(1, num_buckets):
                bucket = buckets[i]
                g = bucket.grids_of_dimension(d)[target_grid]
                cell_map, face_map, node_map = make_maps(
                    g_0, g, bucket.dim_max())
                mapped_cf = g.cell_faces[face_map][:, cell_map]
                mapped_fn = g.face_nodes[node_map][:, face_map]

                assert np.sum(np.abs(g_0.cell_faces) != np.abs(mapped_cf)) == 0
                assert np.sum(np.abs(g_0.face_nodes) != np.abs(mapped_fn)) == 0
                if g.dim == dim_h:
                    face_maps_h.append(face_map)
                    cell_maps_h.append(cell_map)
                else:
                    cell_maps_l[i][g] = cell_map
                    face_maps_l[i][g] = face_map

                # Also loop on the standard face tags to check that they are
                # identical between the buckets.
                tag_keys = tags.standard_face_tags()
                for key in tag_keys:
                    assert np.all(
                        np.isclose(g_0.tags[key], g.tags[key][face_map]))

    # Mortar grids
    g_h_0 = buckets[0].grids_of_dimension(dim_h)[0]
    for target_grid in range(len(buckets[0].grids_of_dimension(dim_l))):
        g_l_0 = buckets[0].grids_of_dimension(dim_l)[target_grid]

        mg_0 = buckets[0].edge_props((g_h_0, g_l_0), "mortar_grid")
        proj_0 = mg_0.primary_to_mortar_int()
        for i in range(1, num_buckets):
            g_l_i = buckets[i].grids_of_dimension(dim_l)[target_grid]
            g_h_i = buckets[i].grids_of_dimension(dim_h)[0]
            mg_i = buckets[i].edge_props((g_h_i, g_l_i), "mortar_grid")
            proj_i = mg_i.primary_to_mortar_int()
            cm = cell_maps_l[i][g_l_i]
            cm_extended = np.append(cm, cm + cm.size)
            fm = face_maps_h[i - 1]
            mapped_fc = proj_i[cm_extended, :][:, fm]
            assert np.sum(np.absolute(proj_0) - np.absolute(mapped_fc)) == 0
    return cell_maps_h, cell_maps_l, face_maps_h, face_maps_l