def test_node_based_ind_3d_bound(self):
        # Nodes of cell 1
        n = np.array([1, 2, 5, 6, 17, 18, 21, 22])
        known_cells = np.array([0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14])
        known_faces = np.array([1, 2, 37, 40, 73, 82])

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_3d,
                                                                 nodes=n)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_3d,
                                                                 nodes=n)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
    def test_face_based_ind_2d_bound(self):
        f = np.array([2])
        known_cells = np.array([0, 1, 2, 3, 5, 6, 7, 8, 11, 12])
        known_faces = np.array([2, 8, 31, 32, 36, 37])
        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                                 faces=f)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
Beispiel #3
0
 def test_face_based_ind_2d_bound(self):
     # Face between cell 1 and 2
     f = np.array([2])
     known_cells = np.array(
         [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18])
     known_faces = np.array([2, 8, 31, 32, 36, 37])
     cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                              faces=f)
     self.assertTrue(np.alltrue(known_cells == cell_ind))
     self.assertTrue(np.alltrue(known_faces == face_ind))
    def test_cell_based_ind_2d(self):

        c = np.array([12])
        known_cells = np.setdiff1d(np.arange(25), np.array([0, 4, 20, 24]))
        known_faces = np.array([8, 9, 14, 15, 20, 21, 41, 42, 43, 46, 47, 48])

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                                 cells=c)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
    def test_node_based_ind_2d_bound(self):
        # Nodes of cell 1
        n = np.array([1, 2, 7, 8])
        known_cells = np.array([0, 1, 2, 5, 6, 7])
        known_faces = np.array([1, 2, 31, 36])

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                                 nodes=n)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
    def test_node_based_ind_2d(self):
        # Nodes of cell 12 (middle one) - from counting
        n = np.array([14, 15, 20, 21])

        known_cells = np.array([6, 7, 8, 11, 12, 13, 16, 17, 18])
        known_faces = np.array([14, 15, 42, 47])

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                                 nodes=n)
        assert np.allclose(known_cells, cell_ind)
        assert np.allclose(known_faces, face_ind)
    def test_cell_based_ind_bound_3d(self):
        c = np.array([1])
        known_cells = np.arange(27)
        fx = np.array([1, 2, 5, 6, 13, 14, 17, 18])
        fy = 36 + np.array([0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, 17])
        fz = 72 + np.array([0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14])
        known_faces = np.hstack((fx, fy, fz))
        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_3d,
                                                                 cells=c)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
    def test_node_based_ind_3d(self):
        # Nodes of cell 13 (middle one) - from counting
        n = np.array([21, 22, 25, 26, 37, 38, 41, 42])

        known_cells = np.arange(27)
        known_faces = np.array([17, 18, 52, 55, 85, 94])

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_3d,
                                                                 nodes=n)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
Beispiel #9
0
    def test_face_based_ind_2d(self):

        # Use face between cells 11 and 12
        f = np.array([14])

        known_cells = np.arange(self.g_2d.num_cells)
        known_faces = np.array([8, 14, 20, 41, 42, 46, 47])
        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                                 faces=f)

        self.assertTrue(np.alltrue(known_cells == cell_ind))
        self.assertTrue(np.alltrue(known_faces == face_ind))
    def test_face_based_ind_2d(self):

        # Use face between cells 11 and 12
        f = np.array([14])

        known_cells = np.array(
            [1, 2, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 21, 22])
        known_faces = np.array([8, 14, 20, 41, 42, 46, 47])
        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_2d,
                                                                 faces=f)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
    def test_cell_based_ind_3d(self):
        # Use cell 13 (middle one)
        c = np.array([13])
        known_cells = np.arange(27)
        fx = np.hstack((np.array([1, 2, 5, 6, 9,
                                  10]), np.array([1, 2, 5, 6, 9, 10]) + 12,
                        np.array([1, 2, 5, 6, 9, 10]) + 24))
        fy = 36 + np.hstack(
            (np.array([3, 4, 5, 6, 7, 8]), np.array([3, 4, 5, 6, 7, 8]) + 12,
             np.array([3, 4, 5, 6, 7, 8]) + 24))
        fz = 72 + np.hstack((np.arange(9) + 9, np.arange(9) + 18))
        known_faces = np.hstack((fx, fy, fz))

        cell_ind, face_ind = fvutils.cell_ind_for_partial_update(self.g_3d,
                                                                 cells=c)

        assert np.alltrue(known_cells == cell_ind)
        assert np.alltrue(known_faces == face_ind)
Beispiel #12
0
def mpfa_partial(g,
                 k,
                 bnd,
                 eta=0,
                 inverter='numba',
                 cells=None,
                 faces=None,
                 nodes=None,
                 apertures=None):
    """
    Run an MPFA discretization on subgrid, and return discretization in terms
    of global variable numbers.

    Scenarios where the method will be used include updates of permeability,
    and the introduction of an internal boundary (e.g. fracture growth).

    The subgrid can be specified in terms of cells, faces and nodes to be
    updated. For details on the implementation, see
    fv_utils.cell_ind_for_partial_update()

    Parameters:
        g (porepy.grids.grid.Grid): grid to be discretized
        k (porepy.params.tensor.SecondOrderTensor) permeability tensor
        bnd (porepy.params.bc.BoundarCondition) class for boundary conditions
        faces (np.ndarray) faces to be considered. Intended for partial
            discretization, may change in the future
        eta Location of pressure continuity point. Should be 1/3 for simplex
            grids, 0 otherwise. On boundary faces with Dirichlet conditions,
            eta=0 will be enforced.
        inverter (string) Block inverter to be used, either numba (default),
            cython or python. See fvutils.invert_diagonal_blocks for details.
        cells (np.array, int, optional): Index of cells on which to base the
            subgrid computation. Defaults to None.
        faces (np.array, int, optional): Index of faces on which to base the
            subgrid computation. Defaults to None.
        nodes (np.array, int, optional): Index of nodes on which to base the
            subgrid computation. Defaults to None.
        apertures (np.ndarray, float, optional) apertures of the cells for scaling of the face
            normals. Defaults to None.

        Note that if all of {cells, faces, nodes} are None, empty matrices will
        be returned.

    Returns:
        sps.csr_matrix (g.num_faces x g.num_cells): Flux discretization,
            computed on a subgrid.
        sps.csr_matrix (g,num_faces x g.num_faces): Boundary flux
            discretization, computed on a subgrid
        np.array (int): Global of the faces where the flux discretization is
            computed.

    """
    if cells is not None:
        warnings.warn('Cells keyword for partial mpfa has not been tested')
    if faces is not None:
        warnings.warn('Faces keyword for partial mpfa has not been tested')

    # Find computational stencil, based on specified cells, faces and nodes.
    ind, active_faces = fvutils.cell_ind_for_partial_update(g,
                                                            cells=cells,
                                                            faces=faces,
                                                            nodes=nodes)

    # Extract subgrid, together with mappings between local and global
    # cells
    sub_g, l2g_faces, _ = partition.extract_subgrid(g, ind)
    l2g_cells = sub_g.parent_cell_ind

    # Local parameter fields
    # Copy permeability field, and restrict to local cells
    loc_k = k.copy()
    loc_k.perm = loc_k.perm[::, ::, l2g_cells]

    glob_bound_face = g.get_all_boundary_faces()

    # Boundary conditions are slightly more complex. Find local faces
    # that are on the global boundary.
    loc_bound_ind = np.argwhere(np.in1d(l2g_faces, glob_bound_face)).ravel('F')
    loc_cond = np.array(loc_bound_ind.size * ['neu'])
    # Then pick boundary condition on those faces.
    if loc_bound_ind.size > 0:
        # We could have avoided to explicitly define Neumann conditions,
        # since these are default.
        # For primal-like discretizations like the MPFA, internal boundaries
        # are handled by assigning Neumann conditions.
        is_dir = np.logical_and(bnd.is_dir, np.logical_not(bnd.is_internal))
        is_neu = np.logical_or(bnd.is_neu, bnd.is_internal)

        is_dir = is_dir[l2g_faces[loc_bound_ind]]
        is_neu = is_neu[l2g_faces[loc_bound_ind]]

        loc_cond[is_dir] = 'dir'
    loc_bnd = bc.BoundaryCondition(sub_g, faces=loc_bound_ind, cond=loc_cond)

    # Discretization of sub-problem
    flux_loc, bound_flux_loc = _mpfa_local(sub_g,
                                           loc_k,
                                           loc_bnd,
                                           eta=eta,
                                           inverter=inverter,
                                           apertures=apertures)

    # Map to global indices
    face_map, cell_map = fvutils.map_subgrid_to_grid(g,
                                                     l2g_faces,
                                                     l2g_cells,
                                                     is_vector=False)
    flux_glob = face_map * flux_loc * cell_map
    bound_flux_glob = face_map * bound_flux_loc * face_map.transpose()

    # By design of mpfa, and the subgrids, the discretization will update faces
    # outside the active faces. Kill these.
    outside = np.setdiff1d(np.arange(g.num_faces),
                           active_faces,
                           assume_unique=True)
    flux_glob[outside, :] = 0
    bound_flux_glob[outside, :] = 0

    return flux_glob, bound_flux_glob, active_faces