Beispiel #1
0
 def test_merge_grids_reverse_order(self):
     g = pp.TensorGrid(np.arange(3))
     h = pp.TensorGrid(np.arange(3))
     h.nodes = h.nodes[:, ::-1]
     g.compute_geometry()
     h.compute_geometry()
     weights, new, old = pp.match_grids.match_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))
Beispiel #2
0
    def test_merge_grids_non_matching(self):
        g = pp.TensorGrid(np.arange(3))
        h = pp.TensorGrid(np.arange(3))
        h.nodes[0, 1] = 0.5
        g.compute_geometry()
        h.compute_geometry()
        weights, new, old = pp.match_grids.match_1d(g, h, tol=1e-4)

        # Weights give mappings from h to g. The first cell in h is
        # fully within the first cell in g. The second in h is split 1/3
        # in first of g, 2/3 in second.
        self.assertTrue(np.allclose(weights, np.array([1, 1.0 / 3, 2.0 / 3])))
        self.assertTrue(np.allclose(new, np.array([0, 0, 1])))
        self.assertTrue(np.allclose(old, np.array([0, 1, 1])))
Beispiel #3
0
def test_1d_ambient_dim_1(method):
    dx = np.random.rand(1)[0]
    g = pp.TensorGrid(np.array([0, dx, 2 * dx]))

    ambient_dim = 1
    flux, vector_source_discr, div = set_params_disrcetize(
        g, ambient_dim, method)

    # Prepare to solve problem
    A = div * flux
    rhs = -div * vector_source_discr

    # Make source strength another random number
    grav_strength = np.random.rand(1)

    # introduce a source term in x-direction
    g_x = np.zeros(g.num_cells * ambient_dim)
    g_x[::ambient_dim] = -1 * grav_strength  # /2 * dx
    p_x = np.linalg.pinv(A.toarray()).dot(rhs * g_x)

    # The solution should decrease with increasing x coordinate, with magnitude
    # controlled by grid size and source stregth
    assert np.allclose(p_x[0] - p_x[1], dx * grav_strength)

    flux_x = flux * p_x + vector_source_discr * g_x
    # The net flux should still be zero
    assert np.allclose(flux_x, 0)
Beispiel #4
0
    def generate_2d_grid(self, n, xmax, ymax):
        g1 = pp.CartGrid([xmax * n, ymax * n], physdims=[xmax, ymax])
        g1.compute_geometry()
        gb = pp.GridBucket()

        gb.add_nodes(g1)
        tol = 1e-6
        left_faces = np.argwhere(g1.face_centers[1] > ymax - tol).ravel()
        right_faces = np.argwhere(g1.face_centers[1] < 0 + tol).ravel()
        val = np.ones(left_faces.size, dtype=np.bool)
        shape = [g1.num_faces, g1.num_faces]

        face_faces = sps.coo_matrix((val, (right_faces, left_faces)), shape=shape)

        gb.add_edge((g1, g1), face_faces)

        mg = pp.TensorGrid(np.linspace(0, xmax, n + 1))
        mg.nodes[1] = ymax

        mg.compute_geometry()

        d_e = gb.edge_props((g1, g1))
        d_e["mortar_grid"] = pp.BoundaryMortar(g1.dim - 1, mg, face_faces)
        gb.assign_node_ordering()
        return gb
    def test_merge_1d_grids_partly_equal_nodes(self):
        g = pp.TensorGrid(np.array([0, 1, 2]))
        h = pp.TensorGrid(np.array([0, 0.5, 1, 2]))
        g.compute_geometry()
        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, tol=1e-4)

        self.assertTrue(np.allclose(gh.nodes[:, g_in_comb], g.nodes[:, g_sort]))
        self.assertTrue(np.allclose(gh.nodes[:, h_in_comb], h.nodes[:, h_sort]))
Beispiel #6
0
 def grid_1d(self, n_nodes=2):
     x = np.linspace(0, 1, n_nodes)
     g = pp.TensorGrid(x)
     g.nodes = np.tile(x, (3, 1))
     g.compute_geometry()
     g.global_point_ind = 1 + np.arange(n_nodes)
     return g
    def test_merge_1d_grids_equal_nodes(self):
        g = pp.TensorGrid(np.array([0, 1, 2]))
        g.compute_geometry()
        h, offset, g_in_comb, g_in_comb, g_sort, _ = non_conforming.merge_1d_grids(
            g, g, global_ind_offset=0, tol=1e-4
        )

        self.assertTrue(np.allclose(h.nodes[:, g_in_comb], g.nodes[:, g_sort]))
Beispiel #8
0
 def grid_1d(self, num_pts=3) -> pp.Grid:
     g = pp.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
Beispiel #9
0
    def test_merge_grids_all_common(self):
        g = pp.TensorGrid(np.arange(3))
        g.compute_geometry()
        weights, new, old = pp.match_grids.match_1d(g, g, tol=1e-4)

        self.assertTrue(np.allclose(weights, np.ones(2)))
        self.assertTrue(np.allclose(old, np.arange(2)))
        self.assertTrue(np.allclose(new, np.arange(2)))
    def test_merge_1d_permuted_nodes(self):
        g = pp.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 = pp.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)
        self.assertTrue(ismem.sum() == c.num_nodes)
        self.assertTrue(np.allclose(g.nodes[:, maps], c.nodes))
        ismem, maps = ismember_rows(c.global_point_ind, h.global_point_ind)
        self.assertTrue(ismem.sum() == c.num_nodes)
        self.assertTrue(np.allclose(h.nodes[:, maps], c.nodes))
    def test_merge_1d_grids_rotation(self):
        # 1d grids rotated
        g = pp.TensorGrid(np.array([0, 1, 2]))
        g.nodes = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]]).T
        g.compute_geometry()
        h = pp.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)
        self.assertTrue(np.allclose(gh.nodes[:, g_in_comb], g.nodes[:, g_sort]))
        self.assertTrue(np.allclose(gh.nodes[:, h_in_comb], h.nodes[:, h_sort]))
    def test_merge_two_grids(self):
        # Merge two grids that have a common face. Check that global indices are
        # updated to match, and that they point to the same point coordinates
        data = np.ones(3)
        rows = np.array([0, 1, 2])
        cols = np.array([0, 0, 0])
        cf = 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 = sps.coo_matrix((data, (rows, cols)))
        nodes_1 = np.array([[0, 1, 0], [0, 0, 1], [0, 0, 0]])
        nodes_2 = np.array([[0, 1, 0], [0, 0, -1], [0, 0, 0]])
        g1 = MockGrid(
            2, num_faces=3, face_nodes=fn, cell_faces=cf, num_cells=1, nodes=nodes_1
        )

        g2 = MockGrid(
            2, num_faces=3, face_nodes=fn, cell_faces=cf, num_cells=1, nodes=nodes_2
        )
        g_11 = pp.TensorGrid(np.array([0, 1]))
        g_11.global_point_ind = np.arange(2)
        g_22 = pp.TensorGrid(np.array([0, 1]))
        g_22.global_point_ind = np.arange(2)

        gl = [[[g1], [g_11]], [[g2], [g_22]]]
        intersections = [np.array([1]), 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
        )

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

        ismem, maps = ismember_rows(g_1d.global_point_ind, g2.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g2.nodes[:, maps], g_1d.nodes))
Beispiel #13
0
def _extrude_0d(
    g: pp.PointGrid, z: np.ndarray
) -> Tuple[pp.Grid, np.ndarray, np.ndarray]:
    """ Extrude a 0d grid into 1d by prismatic extension in the z-direction.

    The original grid is assumed to be in the xy-plane, that is, any existing non-zero
    z-direction is ignored.

    Both the original and the new grid will have their geometry computed.

    Parameters:
        g (pp.Grid): Original grid to be extruded. Should have dimension 1.
        z (np.ndarray): z-coordinates of the nodes in the extruded grid. Should be
            either non-negative or non-positive, and be sorted in increasing or
            decreasing order, respectively.

    Returns:
        pp.TensorGrid: A grid of dimension 1.
        np.array of np.arrays: Cell mappings, so that element ci gives all indices of
            cells in the extruded grid that comes from cell ci in the original grid.
        np.array of np.arrays: Face mappings, so that element fi gives all indices of
            faces in the extruded grid that comes from face fi in the original grid.

    """
    # Number of nodes
    num_pt = z.size

    # x and y coordinates of the right size
    x = g.nodes[0, 0] * np.ones(num_pt)
    y = g.nodes[1, 0] * np.ones(num_pt)

    # Initial 1d grid. Coordinates are wrong, but this we will fix later
    # There is no need to do anything special with tags here; the tags of a 0d grid are
    # trivial, and the 1d extrusion can be based on this.
    g_new = pp.TensorGrid(x)

    g_info = g.name.copy()
    g_info.append("Extrude 0d->1d")
    g_new.name = g_info

    # Update coordinates
    g_new.nodes = np.vstack((x, y, z))

    g_new.compute_geometry()

    # The single cell in g has produced all cells in g_new
    cell_map = np.empty(1, dtype=np.object)
    cell_map[0] = np.arange(g_new.num_cells)
    face_map = np.empty(0)

    return g_new, cell_map, face_map
Beispiel #14
0
    def test_merge_grids_split(self):
        g1 = pp.TensorGrid(np.linspace(0, 2, 2))
        g2 = pp.TensorGrid(np.linspace(2, 4, 2))
        g_nodes = np.hstack((g1.nodes, g2.nodes))
        g_face_nodes = sps.block_diag((g1.face_nodes, g2.face_nodes), "csc")
        g_cell_faces = sps.block_diag((g1.cell_faces, g2.cell_faces), "csc")
        g = pp.Grid(1, g_nodes, g_face_nodes, g_cell_faces, "pp.TensorGrid")

        h1 = pp.TensorGrid(np.linspace(0, 2, 3))
        h2 = pp.TensorGrid(np.linspace(2, 4, 3))
        h_nodes = np.hstack((h1.nodes, h2.nodes))
        h_face_nodes = sps.block_diag((h1.face_nodes, h2.face_nodes), "csc")
        h_cell_faces = sps.block_diag((h1.cell_faces, h2.cell_faces), "csc")
        h = pp.Grid(1, h_nodes, h_face_nodes, h_cell_faces, "pp.TensorGrid")

        g.compute_geometry()
        h.compute_geometry()
        weights, new, old = pp.match_grids.match_1d(g, h, tol=1e-4)

        # Weights give mappings from h to g. All cells are split in two
        self.assertTrue(np.allclose(weights, np.array([1.0, 1.0, 1.0, 1.0])))
        self.assertTrue(np.allclose(new, np.array([0, 0, 1, 1])))
        self.assertTrue(np.allclose(old, np.array([0, 1, 2, 3])))
Beispiel #15
0
    def generate_grids(self, n, xmax, ymax, split):
        g1 = pp.CartGrid([split * n, ymax * n], physdims=[split, ymax])
        g2 = pp.CartGrid([(xmax - split) * n, ymax * n],
                         physdims=[xmax - split, ymax])
        g2.nodes[0] += split

        g1.compute_geometry()
        g2.compute_geometry()
        grids = [g2, g1]

        gb = pp.GridBucket()

        [gb.add_nodes(g) for g in grids]
        [g2, g1] = gb.grids_of_dimension(2)

        tol = 1e-6
        if np.any(g2.cell_centers[0] > split):
            right_grid = g2
            left_grid = g1
        else:
            right_grid = g1
            left_grid = g2

        gb.set_node_prop(left_grid, "node_number", 1)
        gb.set_node_prop(right_grid, "node_number", 0)
        left_faces = np.argwhere(
            left_grid.face_centers[0] > split - tol).ravel()
        right_faces = np.argwhere(
            right_grid.face_centers[0] < split + tol).ravel()
        val = np.ones(left_faces.size, dtype=np.bool)
        shape = [right_grid.num_faces, left_grid.num_faces]

        face_faces = sps.coo_matrix((val, (right_faces, left_faces)),
                                    shape=shape)

        gb.add_edge((right_grid, left_grid), face_faces)

        mg = pp.TensorGrid(np.array([split] * ((n + 1) * ymax)))
        mg.nodes[1] = np.linspace(0, ymax, (n + 1) * ymax)
        mg.compute_geometry()
        side_g = {pp.grids.mortar_grid.LEFT_SIDE: mg}

        d_e = gb.edge_props((g1, g2))
        d_e["mortar_grid"] = pp.BoundaryMortar(g1.dim - 1, side_g, face_faces)
        d_e["edge_number"] = 0

        return gb
Beispiel #16
0
 def grid_1d(self, num_pts=3, rotate_fracture=False):
     g = pp.TensorGrid(np.arange(num_pts))
     if rotate_fracture:
         g.nodes = np.vstack((
             np.linspace(0.4, 0.6, num_pts),
             np.linspace(0.25, 0.75, num_pts),
             np.zeros(num_pts),
         ))
     else:
         g.nodes = np.vstack((
             0.5 * np.ones(num_pts),
             np.linspace(0.25, 0.75, num_pts),
             np.zeros(num_pts),
         ))
     g.compute_geometry()
     g.global_point_ind = np.arange(g.num_nodes)
     return g
Beispiel #17
0
    def test_cart_1d(self):
        g = pp.TensorGrid(np.array([0, 1, 2]))
        g.nodes = g.nodes + 0.2 * np.random.random(g.nodes.shape)
        g.compute_geometry()

        face_pos = [0, 1, 2]

        for f in face_pos:
            h, sub_f, sub_n = pp.partition.extract_subgrid(g, f, faces=True)

            true_nodes = np.array([f])
            true_faces = np.array([f])

            self.assertTrue(np.array_equal(true_nodes, sub_n))
            self.assertTrue(np.array_equal(true_faces, sub_f))

            self.compare_grid_geometries(g, h, f, true_faces, true_nodes)
Beispiel #18
0
def _create_embedded_2d_grid(loc_coord, glob_id):
    """
    Create a 2d grid that is embedded in a 3d grid.
    """
    loc_center = np.mean(loc_coord, axis=1).reshape((-1, 1))
    loc_coord -= loc_center
    # Check that the points indeed form a line
    assert pp.geometry_property_checks.points_are_planar(loc_coord)
    # Find the tangent of the line
    # Projection matrix
    rot = pp.map_geometry.project_plane_matrix(loc_coord)
    loc_coord_2d = rot.dot(loc_coord)
    # The points are now 2d along two of the coordinate axis, but we
    # don't know which yet. Find this.
    sum_coord = np.sum(np.abs(loc_coord_2d), axis=1)
    active_dimension = np.logical_not(np.isclose(sum_coord, 0))
    # Check that we are indeed in 2d
    assert np.sum(active_dimension) == 2
    # Sort nodes, and create grid
    coord_2d = loc_coord_2d[active_dimension]
    sort_ind = np.lexsort((coord_2d[0], coord_2d[1]))
    sorted_coord = coord_2d[:, sort_ind]
    sorted_coord = np.round(sorted_coord * 1e10) / 1e10
    unique_x = np.unique(sorted_coord[0])
    unique_y = np.unique(sorted_coord[1])
    # assert unique_x.size == unique_y.size
    g = pp.TensorGrid(unique_x, unique_y)
    assert np.all(g.nodes[0:2] - sorted_coord == 0)

    # Project back to active dimension
    nodes = np.zeros(g.nodes.shape)
    nodes[active_dimension] = g.nodes[0:2]
    g.nodes = nodes
    # Project back again to 3d coordinates

    irot = rot.transpose()
    g.nodes = irot.dot(g.nodes)
    g.nodes += loc_center

    # Add mapping to global point numbers
    g.global_point_ind = glob_id[sort_ind]
    return g
Beispiel #19
0
def create_embedded_line_grid(loc_coord: np.ndarray,
                              glob_id: np.ndarray,
                              tol: float = 1e-4) -> pp.Grid:
    """
    Create a 1d grid embedded in a higher dimensional space.

    Args:
        loc_coord (np.ndarray): Coordinates of points to be used in the grid.
        glob_id (np.ndarray): Global indexes of the points. Typically refers to a global
            mesh, where the points of this grid is a subset.
        tol (float, optional): Tolerance used for check of collinearity of the points.
            Defaults to 1e-4.

    Returns:
        g (TYPE): DESCRIPTION.

    """
    loc_center = np.mean(loc_coord, axis=1).reshape((-1, 1))
    (
        sorted_coord,
        rot,
        active_dimension,
        sort_ind,
    ) = pp.map_geometry.project_points_to_line(loc_coord, tol)
    g = pp.TensorGrid(sorted_coord)

    # Project back to active dimension
    nodes = np.zeros(g.nodes.shape)
    nodes[active_dimension] = g.nodes[0]
    g.nodes = nodes

    # Project back again to 3d coordinates
    irot = rot.transpose()
    g.nodes = irot.dot(g.nodes)
    g.nodes += loc_center

    # Add mapping to global point numbers
    g.global_point_ind = glob_id[sort_ind]
    return g
    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 = pp.TensorGrid(np.array([0, 1]))
        g_11.global_point_ind = np.arange(2)
        # Top 1d grid, as seen from g1
        g_13 = pp.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 = pp.TensorGrid(np.array([0, 1]))
        g_22.global_point_ind = np.arange(2)
        # Top 1d grid, as seen from g3
        g_33 = pp.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
        )
        self.assertTrue(len(grid_list_1d) == 2)

        g_1d = grid_list_1d[0]
        ismem, maps = ismember_rows(g_1d.global_point_ind, g1.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g1.nodes[:, maps], g_1d.nodes))
        ismem, maps = ismember_rows(g_1d.global_point_ind, g2.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(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)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g1.nodes[:, maps], g_1d.nodes))
        ismem, maps = ismember_rows(g_1d.global_point_ind, g3.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g3.nodes[:, maps], g_1d.nodes))
    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 = pp.TensorGrid(np.array([0, 1, 2]))
        g_11.global_point_ind = np.arange(3)
        # Second 1d grid, as seen from g1
        g_13 = pp.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 = pp.TensorGrid(np.array([0, 2]))
        g_22.global_point_ind = np.arange(2)
        # Second 1d grid, as seen from g3
        g_33 = pp.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
        )
        self.assertTrue(len(grid_list_1d) == 2)

        g_1d = grid_list_1d[0]
        ismem, maps = ismember_rows(g_1d.global_point_ind, g1.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g1.nodes[:, maps], g_1d.nodes))
        ismem, maps = ismember_rows(g_1d.global_point_ind, g2.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(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)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g1.nodes[:, maps], g_1d.nodes))
        ismem, maps = ismember_rows(g_1d.global_point_ind, g3.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(g3.nodes[:, maps], g_1d.nodes))
Beispiel #22
0
 def setUp(self):
     self.x = np.array([0, 1, 3])
     self.y = np.array([1, 3, 7])
     self.g = pp.TensorGrid(self.x)
     self.g.nodes = np.vstack((self.x, self.y, np.zeros(3)))
Beispiel #23
0
def merge_1d_grids(g, h, global_ind_offset=0, tol=1e-4):
    """Merge two 1d grids with non-matching nodes to a single grid.

    The grids should have common start and endpoints. They can be into 3d space
    in a genreal way.

    The function is primarily intended for merging non-conforming DFN grids.

    Parameters:
        g: 1d tensor grid.
        h: 1d tensor grid
        glob_ind_offset (int, defaults to 0): Off set for the global point
            index of the new grid.
        tol (double, defaults to 1e-4): Tolerance for when two nodes are merged
            into one.

    Returns:
        TensorGrid: New tensor grid, containing the combined node definition.
        int: New global ind offset, increased by the number of cells in the
            combined grid.
        np.array (int): Indices of common nodes (after sorting) of g and the
            new grid.
        np.array (int): Indices of common nodes (after sorting) of h and the
            new grid.
        np.array (int): Permutation indices that sort the node coordinates of
            g. The common indices between g and the new grid are found as
            new_grid.nodes[:, g_in_combined] = g.nodes[:, sorted]
        np.array (int): Permutation indices that sort the node coordinates of
            h. The common indices between h and the new grid are found as
            new_grid.nodes[:, h_in_combined] = h.nodes[:, sorted]

    """

    # Nodes of the two 1d grids, combine them
    gp = g.nodes
    hp = h.nodes
    combined = np.hstack((gp, hp))

    num_g = gp.shape[1]
    num_h = hp.shape[1]

    # Keep track of where we put the indices of the original grids
    g_in_full = np.arange(num_g)
    h_in_full = num_g + np.arange(num_h)

    # The tolerance should not be larger than the smallest distance between
    # two points on any of the grids.
    diff_gp = np.min(pp.distances.pointset(gp, True))
    diff_hp = np.min(pp.distances.pointset(hp, True))
    min_diff = np.minimum(tol, 0.5 * np.minimum(diff_gp, diff_hp))

    # Uniquify points
    combined_unique, _, new_2_old = unique_columns_tol(combined, tol=min_diff)
    # Follow locations of the original grid points
    g_in_unique = new_2_old[g_in_full]
    h_in_unique = new_2_old[h_in_full]

    # The combined nodes must be sorted along their natural line.
    # Find the dimension with the largest spatial extension, and sort those
    # coordinates
    max_coord = combined_unique.max(axis=1)
    min_coord = combined_unique.min(axis=1)
    dx = max_coord - min_coord
    sort_dim = np.argmax(dx)

    sort_ind = np.argsort(combined_unique[sort_dim])
    combined_sorted = combined_unique[:, sort_ind]

    # Follow the position of the orginial nodes through sorting
    _, g_sorted = ismember_rows(g_in_unique, sort_ind)
    _, h_sorted = ismember_rows(h_in_unique, sort_ind)

    num_new_grid = combined_sorted.shape[1]

    # Create a new 1d grid.
    # First use a 1d coordinate to initialize topology
    new_grid = pp.TensorGrid(np.arange(num_new_grid))
    # Then set the right, 3d coordinates
    new_grid.nodes = pp.map_geometry.force_point_collinearity(combined_sorted)

    # Set global point indices
    new_grid.global_point_ind = global_ind_offset + np.arange(num_new_grid)
    global_ind_offset += num_new_grid

    return (
        new_grid,
        global_ind_offset,
        g_sorted,
        h_sorted,
        np.arange(num_g),
        np.arange(num_h),
    )
    def test_merge_three_grids_internal_intersection_hanging_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(20)
        rows = np.array([0, 1, 1, 2, 2, 3, 0, 4, 0, 5, 1, 4, 2, 4, 2, 5, 3, 4, 3, 5])
        cols = np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9])
        fn_1 = sps.coo_matrix((data, (rows, cols)))

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

        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_2 = 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_2 = sps.coo_matrix((data, (rows, cols)))

        nodes_1 = np.array(
            [[-1, -0.5, 0, 1, 0, 0], [0, 0, 0, 0, -1, 1], [0, 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=10,
            face_nodes=fn_1,
            cell_faces=cf_1,
            num_cells=5,
            nodes=nodes_1,
        )
        # First neighboring grid
        gxz = MockGrid(
            2, num_faces=8, face_nodes=fn_2, cell_faces=cf_2, num_cells=4, nodes=nodes_2
        )
        gyz = MockGrid(
            2, num_faces=8, face_nodes=fn_2, cell_faces=cf_2, num_cells=4, nodes=nodes_3
        )

        # First 1d grid, as seen from g1
        g_1x = pp.TensorGrid(np.array([0, 1, 2, 3]))
        g_1x.nodes = np.array([[-1, -0.5, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]])
        g_1x.global_point_ind = np.arange(4)
        # Third 1d grid, as seen from g1
        g_1y = pp.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([4, 2, 5])

        # First 1d grid, as seen from g2
        g_2x = pp.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 = pp.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 = pp.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 = pp.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 = [[[gxz], [g_2z, g_2x]], [[gyz], [g_3z, g_3y]], [[gxy], [g_1x, g_1y]]]
        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
        )
        self.assertTrue(len(grid_list_1d) == 3)

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

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

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

        ismem, maps = ismember_rows(g_1d.global_point_ind, gyz.global_point_ind)
        self.assertTrue(ismem.sum() == g_1d.num_nodes)
        self.assertTrue(np.allclose(gyz.nodes[:, maps], g_1d.nodes))