예제 #1
0
    def test_merge_1d_grids_rotation(self):
        #1d grids rotated
        g = TensorGrid(np.array([0, 1, 2]))
        g.nodes = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]]).T
        g.compute_geometry()
        h = TensorGrid(np.array([0, 1, 2]))
        h.nodes = np.array([[0, 0, 0], [0.5, 0.5, 0.5], [2, 2, 2]]).T
        h.compute_geometry()

        gh, offset, g_in_comb, h_in_comb , g_sort, h_sort =\
            non_conforming.merge_1d_grids(g, h, global_ind_offset=0)
        assert np.allclose(gh.nodes[:, g_in_comb], g.nodes[:, g_sort])
        assert np.allclose(gh.nodes[:, h_in_comb], h.nodes[:, h_sort])
예제 #2
0
 def grid_1d(self, n_nodes=2):
     x = np.linspace(0, 1, n_nodes)
     g = TensorGrid(x)
     g.nodes = np.tile(x, (3, 1))
     g.compute_geometry()
     g.global_point_ind = 1 + np.arange(n_nodes)
     return g
예제 #3
0
 def grid_1d(self, num_pts=3):
     g = TensorGrid(np.arange(num_pts))
     g.nodes = np.vstack(
         (np.linspace(0, 1,
                      num_pts), 0.5 * np.ones(num_pts), np.zeros(num_pts)))
     g.compute_geometry()
     g.global_point_ind = np.arange(g.num_nodes)
     return g
예제 #4
0
 def test_refinement_grid_1d_general_orientation(self):
     x = np.array([0, 2, 6]) * np.ones((3, 1))
     g = TensorGrid(x[0])
     g.nodes = x
     h = refinement.refine_grid_1d(g, ratio=2)
     self.assertTrue(
         np.allclose(
             h.nodes,
             np.array([[0, 1, 2, 4, 6], [0, 1, 2, 4, 6], [0, 1, 2, 4, 6]])))
예제 #5
0
def remesh_1d(g_old: pp.Grid,
              num_nodes: int,
              tol: Optional[float] = 1e-6) -> pp.Grid:
    """Create a new 1d mesh covering the same domain as an old one.

    The new grid is equispaced, and there is no guarantee that the nodes in
    the old and new grids are coincinding. Use with care, in particular for
    grids with internal boundaries.

    Parameters:
        g_old (pp.Grid): 1d grid to be replaced.
        num_nodes (int): Number of nodes in the new grid.
        tol (double, optional): Tolerance used to compare node coornidates
            (for mapping of boundary conditions). Defaults to 1e-6.

    Returns:
        pp.Grid: New grid.

    """

    # Create equi-spaced nodes covering the same domain as the old grid
    theta = np.linspace(0, 1, num_nodes)
    start, end = g_old.get_all_boundary_nodes()
    # Not sure why the new axis was necessary.
    nodes = g_old.nodes[:, start,
                        np.newaxis] * theta + g_old.nodes[:, end,
                                                          np.newaxis] * (1.0 -
                                                                         theta)

    # Create the new grid, and assign nodes.
    g = TensorGrid(nodes[0, :])
    g.nodes = nodes
    g.compute_geometry()

    # map the tags from the old grid to the new one
    # normally the tags are given at faces/point that are fixed the 1d mesh
    # we use this assumption to proceed.
    for f_old in np.arange(g_old.num_faces):
        # detect in the new grid which face is geometrically the same (upon a tolerance)
        # as in the old grid
        dist = pp.distances.point_pointset(g_old.face_centers[:, f_old],
                                           g.face_centers)
        f_new = np.where(dist < tol)[0]

        # if you find a match transfer all the tags from the face in the old grid to
        # the face in the new grid
        if f_new.size:
            if f_new.size != 1:
                raise ValueError(
                    "It cannot be more than one face, something went wrong")
            for tag in pp.utils.tags.standard_face_tags():
                g.tags[tag][f_new] = g_old.tags[tag][f_old]

    g.update_boundary_node_tag()

    return g
예제 #6
0
def remesh_1d(g_old, num_nodes, tol=1e-6):
    """ Create a new 1d mesh covering the same domain as an old one.

    The new grid is equispaced, and there is no guarantee that the nodes in
    the old and new grids are coincinding. Use with care, in particular for
    grids with internal boundaries.

    Parameters:
        g_old (grid): 1d grid to be replaced.
        num_nodes (int): Number of nodes in the new grid.
        tol (double, optional): Tolerance used to compare node coornidates
            (for mapping of boundary conditions). Defaults to 1e-6.

    Returns:
        grid: New grid.

    """

    # Create equi-spaced nodes covering the same domain as the old grid
    theta = np.linspace(0, 1, num_nodes)
    start, end = g_old.get_boundary_nodes()
    # Not sure why the new axis was necessary.
    nodes = g_old.nodes[:, start,
                        np.newaxis] * theta + g_old.nodes[:, end,
                                                          np.newaxis] * (1. -
                                                                         theta)

    # Create the new grid, and assign nodes.
    g = TensorGrid(nodes[0, :])
    g.nodes = nodes
    g.compute_geometry()

    # map the tags from the old grid to the new one

    # retrieve the old faces and the corresponding coordinates
    old_frac_faces = np.where(g_old.tags["fracture_faces"].ravel())[0]

    # compute the mapping from the old boundary to the new boundary
    # we need to go through the coordinates

    new_frac_face = []

    for fi in old_frac_faces:
        nfi = np.where(
            cg.dist_point_pointset(g_old.face_centers[:, fi], nodes) < tol)[0]
        if len(nfi) > 0:
            new_frac_face.append(nfi[0])

    # This can probably be made more elegant
    g.tags["fracture_faces"][new_frac_face] = True

    # Fracture tips should be on the boundary only.
    if np.any(g_old.tags["tip_faces"]):
        g.tags["tip_faces"] = g.tags["domain_boundary_faces"]

    return g
예제 #7
0
 def create_1d_from_nodes(nodes):
     # From a set of nodes, create a 1d grid. duplicate nodes are removed
     # and we verify that the nodes are indeed colinear
     assert cg.is_collinear(nodes, tol=tol)
     sort_ind = cg.argsort_point_on_line(nodes, tol=tol)
     n = nodes[:, sort_ind]
     unique_nodes, _, _ = unique_columns_tol(n, tol=tol)
     g = TensorGrid(np.arange(unique_nodes.shape[1]))
     g.nodes = unique_nodes
     g.compute_geometry()
     return g, sort_ind
예제 #8
0
    def test_merge_grids_reverse_order(self):
        g = TensorGrid(np.arange(3))
        h = TensorGrid(np.arange(3))
        h.nodes = h.nodes[:, ::-1]
        weights, new, old = mortars.match_grids_1d(g, h, tol=1e-4)

        self.assertTrue(np.allclose(weights, np.array([1, 1])))
        # In this case, we don't know which ordering the combined grid uses
        # Instead, make sure that the two mappings are ordered in separate
        # directions
        self.assertTrue(np.allclose(new[::-1], old))
예제 #9
0
 def create_1d_from_nodes(nodes):
     # From a set of nodes, create a 1d grid. duplicate nodes are removed
     # and we verify that the nodes are indeed colinear
     if not pp.geometry_property_checks.points_are_collinear(nodes, tol=tol):
         raise ValueError("Nodes are not colinear")
     sort_ind = pp.map_geometry.sort_points_on_line(nodes, tol=tol)
     n = nodes[:, sort_ind]
     unique_nodes, _, _ = unique_columns_tol(n, tol=tol)
     g = TensorGrid(np.arange(unique_nodes.shape[1]))
     g.nodes = unique_nodes
     g.compute_geometry()
     return g, sort_ind
예제 #10
0
    def test_merge_1d_permuted_nodes(self):
        g = TensorGrid(np.array([0, 1, 2]))
        g.nodes = np.array([[1, -1, 0], [0, 0, 0], [0, 0, 0]])
        g.global_point_ind = np.array([2, 0, 1])
        g.face_nodes.indices = np.array([1, 2, 0])

        h = TensorGrid(np.array([-1, 0, 1]))
        h.global_point_ind = np.array([0, 1, 2])
        g.compute_geometry()
        h.compute_geometry()
        c, _, _, _, _, _ = non_conforming.merge_1d_grids(g, h)

        ismem, maps = ismember_rows(c.global_point_ind, g.global_point_ind)
        assert ismem.sum() == c.num_nodes
        assert np.allclose(g.nodes[:, maps], c.nodes)
        ismem, maps = ismember_rows(c.global_point_ind, h.global_point_ind)
        assert ismem.sum() == c.num_nodes
        assert np.allclose(h.nodes[:, maps], c.nodes)
예제 #11
0
def dfn(fracs, conforming, intersections=None, keep_geo=False, tol=1e-4,
        **kwargs):
    """ Create a mesh of a DFN model, that is, only of fractures.

    The mesh can eihter be conforming along fracture intersections, or each
    fracture is meshed independently. The latter case will typically require
    some sort of sewing together external to this funciton.

    TODO: What happens if we give in a non-connected network?

    Parameters:
        fracs (either Fractures, or a FractureNetwork).
        conforming (boolean): If True, the mesh will be conforming along 1d
            intersections.
        intersections (list of lists, optional): Each item corresponds to an
            intersection between two fractures. In each sublist, the first two
            indices gives fracture ids (refering to order in fracs). The third
            item is a numpy array representing intersection coordinates. If no
            intersections provided, intersections will be detected using
            function in FractureNetwork.
        **kwargs: Parameters passed to gmsh.

    Returns:
        GridBucket (if conforming is True): Mixed-dimensional mesh that
            represents all fractures, and intersection poitns and line.

    """

    if isinstance(fracs, FractureNetwork) \
       or isinstance(fracs, FractureNetwork_full):
        network = fracs
    else:
        network = FractureNetwork(fracs)

    # Populate intersections in FractureNetowrk, or find intersections if not
    # provided.

    if intersections is not None:
        logger.warn('FractureNetwork use pre-computed intersections')
        network.intersections = [Intersection(*i) for i in intersections]
    else:
        logger.warn('FractureNetwork find intersections in DFN')
        tic = time.time()
        network.find_intersections()
        logger.warn('Done. Elapsed time ' + str(time.time() - tic))

    if conforming:
        logger.warn('Create conforming mesh for DFN network')
        grids = simplex.triangle_grid_embedded(network, find_isect=False,
                                               **kwargs)
    else:
        logger.warn('Create non-conforming mesh for DFN network')
        tic = time.time()
        grid_list = []
        neigh_list = []

        for fi in range(len(network._fractures)):
            logger.info('Meshing of fracture ' + str(fi))
            # Rotate fracture vertexes and intersection points
            fp, ip, other_frac, rot, cp = network.fracture_to_plane(fi)
            frac_i = network[fi]

            f_lines = np.reshape(np.arange(ip.shape[1]), (2, -1), order='F')
            frac_dict = {'points': ip, 'edges': f_lines}
            if keep_geo:
                file_name = 'frac_mesh_' + str(fi)
                kwargs['file_name'] = file_name
            # Create mesh on this fracture surface.
            grids = simplex.triangle_grid(frac_dict, fp, verbose=False,
                                          **kwargs)

            irot = rot.T
            # Loop over grids, rotate back again to 3d coordinates
            for gl in grids:
                for g in gl:
                    g.nodes = irot.dot(g.nodes) + cp

            # Nodes of main (fracture) grid, in 3d coordinates1
            main_nodes = grids[0][0].nodes
            main_global_point_ind = grids[0][0].global_point_ind
            # Loop over intersections, check if the intersection is on the
            # boundary of this fracture.
            for ind, isect in enumerate(network.intersections_of_fracture(fi)):
                of = isect.get_other_fracture(frac_i)
                if isect.on_boundary_of_fracture(frac_i):
                    dist, _, _ = cg.dist_points_polygon(main_nodes, of.p)
                    hit = np.argwhere(dist < tol).reshape((1, -1))[0]
                    nodes_1d = main_nodes[:, hit]
                    global_point_ind = main_global_point_ind[hit]

                    assert cg.is_collinear(nodes_1d, tol=tol)
                    sort_ind = cg.argsort_point_on_line(nodes_1d, tol=tol)
                    g_aux = TensorGrid(np.arange(nodes_1d.shape[1]))
                    g_aux.nodes = nodes_1d[:, sort_ind]
                    g_aux.global_point_ind = global_point_ind[sort_ind]
                    grids[1].insert(ind, g_aux)

            assert len(grids[0]) == 1, 'Fracture should be covered by single'\
                'mesh'

            grid_list.append(grids)
            neigh_list.append(other_frac)

        logger.warn('Finished creating grids. Elapsed time ' +
                    str(time.time() - tic))
        logger.warn('Merge grids')
        tic = time.time()
        grids = non_conforming.merge_grids(grid_list, neigh_list)
        logger.warn('Done. Elapsed time ' + str(time.time() - tic))

        for g_set in grids:
            if len(g_set) > 0:
                s = 'Created ' + str(len(g_set)) + ' ' + str(g_set[0].dim) + \
                    '-d grids with '
                num = 0
                for g in g_set:
                    num += g.num_cells
                s += str(num) + ' cells'
                logger.info(s)

    return grid_list_to_grid_bucket(grids, check_highest_dim=False)
예제 #12
0
    def test_merge_three_grids_internal_intersection_no_hanging_node_reverse_order(
            self):
        # Merge three grids, where a central cell share one face each with the two
        # other. Importantly, one node will be involved in both shared faces.
        data = np.ones(16)
        rows = np.array([0, 1, 1, 2, 0, 3, 0, 4, 1, 3, 1, 4, 2, 3, 2, 4])
        cols = np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7])
        fn = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(12)
        rows = np.array([0, 5, 3, 1, 7, 5, 0, 2, 4, 1, 4, 6])
        cols = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3])
        cf = sps.coo_matrix((data, (rows, cols)))

        nodes_1 = np.array([[-1, 0, 1, 0, 0], [0, 0, 0, -1, 1],
                            [0, 0, 0, 0, 0]])
        nodes_2 = np.array([[-1, 0, 1, 0, 0], [0, 0, 0, 0, 0],
                            [0, 0, 0, -1, 1]])
        nodes_3 = np.array([[0, 0, 0, 0, 0], [-1, 0, 1, 0, 0],
                            [0, 0, 0, -1, 1]])
        # Central grid
        gxy = MockGrid(2,
                       num_faces=8,
                       face_nodes=fn,
                       cell_faces=cf,
                       num_cells=4,
                       nodes=nodes_1)
        # First neighboring grid
        gxz = MockGrid(2,
                       num_faces=8,
                       face_nodes=fn,
                       cell_faces=cf,
                       num_cells=4,
                       nodes=nodes_2)
        gyz = MockGrid(2,
                       num_faces=8,
                       face_nodes=fn,
                       cell_faces=cf,
                       num_cells=4,
                       nodes=nodes_3)

        # First 1d grid, as seen from g1
        g_1x = TensorGrid(np.array([0, 1, 2]))
        g_1x.nodes = np.array([[1, 0, -1], [0, 0, 0], [0, 0, 0]])
        g_1x.global_point_ind = np.array([2, 1, 0])
        #g_1x.face_nodes.indices = np.array([1, 2, 0])
        # Third 1d grid, as seen from g1
        g_1y = TensorGrid(np.array([0, 1, 2]))
        g_1y.nodes = np.array([[0, 0, 0], [-1, 0, 1], [0, 0, 0]])
        # Point indices adjusted according to ordering in nodes_1
        g_1y.global_point_ind = np.array([3, 1, 4])

        # First 1d grid, as seen from g2
        g_2x = TensorGrid(np.array([0, 1, 2]))
        g_2x.nodes = np.array([[-1, 0, 1], [0, 0, 0], [0, 0, 0]])
        g_2x.global_point_ind = np.arange(3)
        # Third 1d grid, as seen from g2
        g_2z = TensorGrid(np.array([0, 1, 2]))
        g_2z.nodes = np.array([[0, 0, 0], [0, 0, 0], [-1, 0, 1]])
        # Point indices adjusted according to ordering in nodes_1
        g_2z.global_point_ind = np.array([3, 1, 4])

        g_3y = TensorGrid(np.array([0, 1, 2]))
        g_3y.nodes = np.array([[0, 0, 0], [-1, 0, 1], [0, 0, 0]])
        g_3y.global_point_ind = np.arange(3)
        # Second 1d grid, as seen from g1
        g_3z = TensorGrid(np.array([0, 1, 2]))
        g_3z.nodes = np.array([[0, 0, 0], [0, 0, 0], [-1, 0, 1]])
        # Point indices adjusted according to ordering in nodes_1
        g_3z.global_point_ind = np.array([3, 1, 4])

        gl = [[[gxy], [g_1x, g_1y]], [[gxz], [g_2x, g_2z]],
              [[gyz], [g_3y, g_3z]]]
        intersections = [np.array([1, 2]), np.array([0, 2]), np.array([0, 1])]

        list_of_grids, glob_ind = non_conforming.init_global_ind(gl)
        grid_list_1d = non_conforming.process_intersections(gl,
                                                            intersections,
                                                            glob_ind,
                                                            list_of_grids,
                                                            tol=1e-4)
        assert len(grid_list_1d) == 3

        g_1d = grid_list_1d[0]
        ismem, maps = ismember_rows(g_1d.global_point_ind,
                                    gxy.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(gxy.nodes[:, maps], g_1d.nodes)
        ismem, maps = ismember_rows(g_1d.global_point_ind,
                                    gxz.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(gxz.nodes[:, maps], g_1d.nodes)

        g_1d = grid_list_1d[1]
        ismem, maps = ismember_rows(g_1d.global_point_ind,
                                    gxy.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(gxy.nodes[:, maps], g_1d.nodes)
        ismem, maps = ismember_rows(g_1d.global_point_ind,
                                    gyz.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(gyz.nodes[:, maps], g_1d.nodes)

        g_1d = grid_list_1d[2]
        ismem, maps = ismember_rows(g_1d.global_point_ind,
                                    gxz.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(gxz.nodes[:, maps], g_1d.nodes)

        ismem, maps = ismember_rows(g_1d.global_point_ind,
                                    gyz.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(gyz.nodes[:, maps], g_1d.nodes)
예제 #13
0
    def test_merge_three_grids_hanging_node_shared_node(self):
        # Merge three grids, where a central cell share one face each with the two
        # other. Importantly, one node will be involved in both shared faces.
        data = np.ones(10)
        rows = np.array([0, 1, 1, 2, 2, 3, 3, 0, 3, 1])
        cols = np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4])
        fn_1 = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(6)
        rows = np.array([0, 1, 1, 2, 2, 0])
        cols = np.array([0, 0, 1, 1, 2, 2])
        fn_2 = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(6)
        rows = np.array([0, 4, 3, 1, 2, 4])
        cols = np.array([0, 0, 0, 1, 1, 1])
        cf_1 = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(3)
        rows = np.array([0, 1, 2])
        cols = np.array([0, 0, 0])
        cf_2 = sps.coo_matrix((data, (rows, cols)))

        nodes_1 = np.array([[0, 1, 2, 1], [0, 0, 0, 1], [0, 0, 0, 0]])
        nodes_2 = np.array([[0, 2, 1], [0, 0, -1], [0, 0, 0]])
        nodes_3 = np.array([[0, 1, 0], [0, 1, 1], [0, 0, 0]])
        # Central grid
        g1 = MockGrid(2,
                      num_faces=5,
                      face_nodes=fn_1,
                      cell_faces=cf_1,
                      num_cells=2,
                      nodes=nodes_1)
        # First neighboring grid
        g2 = MockGrid(2,
                      num_faces=3,
                      face_nodes=fn_2,
                      cell_faces=cf_2,
                      num_cells=1,
                      nodes=nodes_2)
        g3 = MockGrid(2,
                      num_faces=3,
                      face_nodes=fn_2,
                      cell_faces=cf_2,
                      num_cells=1,
                      nodes=nodes_3)

        # First 1d grid, as seen from g1
        g_11 = TensorGrid(np.array([0, 1, 2]))
        g_11.global_point_ind = np.arange(3)
        # Second 1d grid, as seen from g1
        g_13 = TensorGrid(np.array([0, 1]))
        g_13.nodes = np.array([[0, 1], [0, 1], [0, 0]])
        # Point indices adjusted according to ordering in nodes_1
        g_13.global_point_ind = np.array([0, 3])

        # First 1d grid, as seen from g2
        g_22 = TensorGrid(np.array([0, 2]))
        g_22.global_point_ind = np.arange(2)
        # Second 1d grid, as seen from g3
        g_33 = TensorGrid(np.array([0, 1]))
        g_33.nodes = np.array([[0, 1], [0, 1], [0, 0]])
        g_33.global_point_ind = np.arange(2)

        gl = [[[g1], [g_11, g_13]], [[g2], [g_22]], [[g3], [g_33]]]
        intersections = [np.array([1, 2]), np.array([0]), np.array([0])]

        list_of_grids, glob_ind = non_conforming.init_global_ind(gl)
        grid_list_1d = non_conforming.process_intersections(gl,
                                                            intersections,
                                                            glob_ind,
                                                            list_of_grids,
                                                            tol=1e-4)
        assert len(grid_list_1d) == 2

        g_1d = grid_list_1d[0]
        ismem, maps = ismember_rows(g_1d.global_point_ind, g1.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g1.nodes[:, maps], g_1d.nodes)
        ismem, maps = ismember_rows(g_1d.global_point_ind, g2.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g2.nodes[:, maps], g_1d.nodes)

        g_1d = grid_list_1d[1]
        ismem, maps = ismember_rows(g_1d.global_point_ind, g1.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g1.nodes[:, maps], g_1d.nodes)
        ismem, maps = ismember_rows(g_1d.global_point_ind, g3.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g3.nodes[:, maps], g_1d.nodes)
예제 #14
0
    def test_merge_three_grids_no_common_point(self):
        # Merge three grids: One in the mid
        data = np.ones(3)
        rows = np.array([0, 1, 2])
        cols = np.array([0, 0, 0])
        cf_1 = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(6)
        rows = np.array([0, 1, 2, 1, 3, 4])
        cols = np.array([0, 0, 0, 1, 1, 1])
        cf_2 = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(6)
        rows = np.array([0, 1, 1, 2, 2, 0])
        cols = np.array([0, 0, 1, 1, 2, 2])
        fn_1 = sps.coo_matrix((data, (rows, cols)))

        data = np.ones(10)
        rows = np.array([0, 1, 1, 3, 3, 0, 1, 2, 2, 3])
        cols = np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4])
        fn_2 = sps.coo_matrix((data, (rows, cols)))

        nodes_1 = np.array([[0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]])
        nodes_2 = np.array([[0, 1, 0], [0, 0, -1], [0, 0, 0]])
        nodes_3 = np.array([[0, 1, 0], [2, 1, 1], [0, 0, 0]])

        # Middle grid, unit square divided into two. Will have neighbors on top and
        # bottom.
        g1 = MockGrid(2,
                      num_faces=5,
                      face_nodes=fn_2,
                      cell_faces=cf_2,
                      num_cells=2,
                      nodes=nodes_1)
        # Neighbor on bottom
        g2 = MockGrid(2,
                      num_faces=3,
                      face_nodes=fn_1,
                      cell_faces=cf_1,
                      num_cells=1,
                      nodes=nodes_2)
        # Neighbor on top.
        g3 = MockGrid(2,
                      num_faces=3,
                      face_nodes=fn_1,
                      cell_faces=cf_1,
                      num_cells=1,
                      nodes=nodes_3)

        # Bottom 1d grid, as seen from g1
        g_11 = TensorGrid(np.array([0, 1]))
        g_11.global_point_ind = np.arange(2)
        # Top 1d grid, as seen from g1
        g_13 = TensorGrid(np.array([0, 1]))
        g_13.nodes = np.array([[0, 1], [1, 1], [0, 0]])
        # Note global point indices here, in accordance with the ordering in
        # nodes_1
        g_13.global_point_ind = np.array([2, 3])

        # Bottom 1d grid, as seen from g2
        g_22 = TensorGrid(np.array([0, 1]))
        g_22.global_point_ind = np.arange(2)
        # Top 1d grid, as seen from g3
        g_33 = TensorGrid(np.array([1, 2]))
        g_33.nodes = np.array([[0, 1], [1, 1], [0, 0]])
        # Global point indices, as ordered in nodes_3
        g_33.global_point_ind = np.array([1, 2])

        gl = [[[g1], [g_11, g_13]], [[g2], [g_22]], [[g3], [g_33]]]
        intersections = [np.array([1, 2]), np.array([0]), np.array([0])]

        list_of_grids, glob_ind = non_conforming.init_global_ind(gl)
        grid_list_1d = non_conforming.process_intersections(gl,
                                                            intersections,
                                                            glob_ind,
                                                            list_of_grids,
                                                            tol=1e-4)
        assert len(grid_list_1d) == 2

        g_1d = grid_list_1d[0]
        ismem, maps = ismember_rows(g_1d.global_point_ind, g1.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g1.nodes[:, maps], g_1d.nodes)
        ismem, maps = ismember_rows(g_1d.global_point_ind, g2.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g2.nodes[:, maps], g_1d.nodes)

        g_1d = grid_list_1d[1]
        ismem, maps = ismember_rows(g_1d.global_point_ind, g1.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g1.nodes[:, maps], g_1d.nodes)
        ismem, maps = ismember_rows(g_1d.global_point_ind, g3.global_point_ind)
        assert ismem.sum() == g_1d.num_nodes
        assert np.allclose(g3.nodes[:, maps], g_1d.nodes)