Example #1
0
    def test_periodic_bc(self):
        """
        We set up the test case      P
                                |--------|
                                |        |
                              D |    g2  | D
                                |        |
                                |--------|
                                    P

        where D are dirichlet boundaries and P the periodic boundaries.
        We construct periodic solution
               p = sin(pi/xmax * (x - x0)) * cos(2*pi/ymax * (y - y0))
        which gives a source term on the rhs.
        """
        n = 8
        xmax = 1
        ymax = 1
        gb = self.generate_2d_grid(n, xmax, ymax)
        tol = 1e-6

        def analytic_p(x):
            x = x.copy()
            shiftx = xmax / 4
            shifty = ymax / 3
            x[0] = x[0] - shiftx
            x[1] = x[1] - shifty
            p = np.sin(np.pi / xmax * x[0]) * np.cos(2 * np.pi / ymax * x[1])
            px = (
                (np.pi / xmax)
                * np.cos(np.pi / xmax * x[0])
                * np.cos(2 * np.pi / ymax * x[1])
            )
            py = (
                2
                * np.pi
                / ymax
                * np.sin(np.pi / xmax * x[0])
                * np.sin(2 * np.pi / ymax * x[1])
            )
            pxx = -(np.pi / xmax) ** 2 * p
            pyy = -(2 * np.pi / ymax) ** 2 * p
            return p, np.vstack([px, py]), pxx + pyy

        for g, d in gb:
            left = g.face_centers[0] < tol
            right = g.face_centers[0] > xmax - tol
            dir_bc = left + right
            bound = pp.BoundaryCondition(g, dir_bc, "dir")
            bc_val = np.zeros(g.num_faces)
            bc_val[dir_bc], _, _ = analytic_p(g.face_centers[:, dir_bc])

            pa, _, lpc = analytic_p(g.cell_centers)
            src = -lpc * g.cell_volumes
            specified_parameters = {"bc": bound, "bc_values": bc_val, "source": src}
            pp.initialize_default_data(g, d, "flow", specified_parameters)

        for _, d in gb.edges():
            pp.params.data.add_discretization_matrix_keyword(d, "flow")
        self.solve(gb, analytic_p)
Example #2
0
def setup_cart_2d(nx):
    frac1 = np.array([[0.2, 0.8], [0.5, 0.5]])
    frac2 = np.array([[0.5, 0.5], [0.8, 0.2]])
    fracs = [frac1, frac2]
    gb = pp.meshing.cart_grid(fracs, nx, physdims=[1, 1])
    gb.compute_geometry()
    gb.assign_node_ordering()
    kw = "flow"
    aperture = 0.01 / np.max(nx)
    for g, d in gb:
        a = np.power(aperture, gb.dim_max() - g.dim) * np.ones(g.num_cells)
        kxx = np.ones(g.num_cells) * a
        perm = pp.SecondOrderTensor(kxx)
        specified_parameters = {"second_order_tensor": perm}

        if g.dim == 2:
            bound_faces = g.tags["domain_boundary_faces"].nonzero()[0]
            bound = pp.BoundaryCondition(g, bound_faces.ravel("F"),
                                         ["dir"] * bound_faces.size)
            bc_val = np.zeros(g.num_faces)
            bc_val[bound_faces] = g.face_centers[1, bound_faces]
            specified_parameters.update({"bc": bound, "bc_values": bc_val})
        # Initialize data and matrix dictionaries in d
        pp.initialize_default_data(g, d, kw, specified_parameters)

    for e, d in gb.edges():
        # Compute normal permeability
        gl, _ = gb.nodes_of_edge(e)
        kn = 1.0 / aperture
        data = {"normal_diffusivity": kn}
        # Add parameters
        d[pp.PARAMETERS] = pp.Parameters(keywords=[kw], dictionaries=[data])
        # Initialize matrix dictionary
        d[pp.DISCRETIZATION_MATRICES] = {kw: {}}
    return gb
    def setup_biot(self):
        g = pp.CartGrid([5, 5])
        g.compute_geometry()
        stiffness = pp.FourthOrderTensor(np.ones(g.num_cells),
                                         np.ones(g.num_cells))
        bnd = pp.BoundaryConditionVectorial(g)

        specified_data = {
            "fourth_order_tensor": stiffness,
            "bc": bnd,
            "inverter": "python",
            "biot_alpha": 1,
        }
        keyword_mech = "mechanics"
        keyword_flow = "flow"
        data = pp.initialize_default_data(g, {},
                                          keyword_mech,
                                          specified_parameters=specified_data)
        data = pp.initialize_default_data(g, data, keyword_flow)

        discr = pp.Biot()
        discr.discretize(g, data)
        div_u = data[pp.DISCRETIZATION_MATRICES][keyword_flow][
            discr.div_u_matrix_key]
        bound_div_u = data[pp.DISCRETIZATION_MATRICES][keyword_flow][
            discr.bound_div_u_matrix_key]
        stab = data[pp.DISCRETIZATION_MATRICES][keyword_flow][
            discr.stabilization_matrix_key]
        grad_p = data[pp.DISCRETIZATION_MATRICES][keyword_mech][
            discr.grad_p_matrix_key]
        bound_pressure = data[pp.DISCRETIZATION_MATRICES][keyword_mech][
            discr.bound_pressure_matrix_key]

        return g, stiffness, bnd, div_u, bound_div_u, grad_p, stab, bound_pressure
Example #4
0
    def test_two_cart_grids(self):
        """
        We set up the test case -----|---------
                                |    |        |
                                | g1 |    g2  |
                                |    |        |
                                -----|---------
        with a linear pressure increase from left to right
        """
        n = 2
        xmax = 3
        ymax = 1
        split = 2
        gb = self.generate_grids(n, xmax, ymax, split)
        tol = 1e-6
        for g, d in gb:
            left = g.face_centers[0] < tol
            right = g.face_centers[0] > xmax - tol
            dir_bc = left + right
            bound = pp.BoundaryCondition(g, dir_bc, "dir")
            bc_val = np.zeros(g.num_faces)
            bc_val[left] = xmax
            bc_val[right] = 0
            specified_parameters = {"bc": bound, "bc_values": bc_val}
            pp.initialize_default_data(g, d, "flow", specified_parameters)

        for e, d in gb.edges():
            mg = d["mortar_grid"]
            d[pp.PARAMETERS] = pp.Parameters(mg, ["flow"], [{}])
            pp.params.data.add_discretization_matrix_keyword(d, "flow")
        # assign discretization
        data_key = "flow"
        tpfa = pp.Tpfa(data_key)
        coupler = pp.FluxPressureContinuity(data_key, tpfa)
        assembler = test_utils.setup_flow_assembler(gb,
                                                    tpfa,
                                                    data_key,
                                                    coupler=coupler)
        test_utils.solve_and_distribute_pressure(gb, assembler)

        # test pressure
        for g, d in gb:
            self.assertTrue(
                np.allclose(d[pp.STATE]["pressure"], xmax - g.cell_centers[0]))

        # test mortar solution
        for e, d_e in gb.edges():
            mg = d_e["mortar_grid"]
            g2, g1 = gb.nodes_of_edge(e)
            master_to_m = mg.master_to_mortar_avg()
            slave_to_m = mg.slave_to_mortar_avg()

            master_area = master_to_m * g1.face_areas
            slave_area = slave_to_m * g2.face_areas

            self.assertTrue(
                np.allclose(d_e[pp.STATE]["mortar_flux"] / master_area, 1))
            self.assertTrue(
                np.allclose(d_e[pp.STATE]["mortar_flux"] / slave_area, 1))
Example #5
0
    def set_parameters_cell_basis(self, gb: pp.GridBucket, data: Dict):
        """
        Assign parameters for the micro gb. Very simple for now, this must be improved.

        Args:
            gb (TYPE): the micro gb.

        Returns:
            None.

        """
        # First initialize data
        for g, d in gb:

            d["Aavatsmark_transmissibilities"] = True

            domain_boundary = np.logical_and(
                g.tags["domain_boundary_faces"],
                np.logical_not(g.tags["fracture_faces"]),
            )

            boundary_faces = np.where(domain_boundary)[0]
            if domain_boundary.size > 0:
                bc_type = boundary_faces.size * ["dir"]
            else:
                bc_type = np.empty(0)

            bc = pp.BoundaryCondition(g, boundary_faces, bc_type)
            if hasattr(g, "face_on_macro_bound"):
                micro_ind = g.face_on_macro_bound
                macro_ind = g.macro_face_ind

                bc.is_neu[micro_ind] = data["bc_macro"]["bc"].is_neu[macro_ind]
                bc.is_dir[micro_ind] = data["bc_macro"]["bc"].is_dir[macro_ind]

            param = {"bc": bc}
            perm = data["g_data"](g)["second_order_tensor"]
            param["second_order_tensor"] = perm
            param["specific_volume"] = data["g_data"](g)["specific_volume"]

            # Use python inverter for mpfa for small problems, where it does not pay off
            # to fire up numba. The set threshold value is somewhat randomly picked.
            if g.num_cells < 100:
                param["mpfa_inverter"] = "python"

            pp.initialize_default_data(g, d, self.keyword, param)

        for e, d in gb.edges():
            mg = d["mortar_grid"]
            g1, g2 = gb.nodes_of_edge(e)
            param = {}
            if not hasattr(g1, "is_auxiliary") or not g1.is_auxiliary:
                check_P = mg.secondary_to_mortar_avg()
                param.update(data["e_data"](mg, g1, g2, check_P))

            pp.initialize_data(mg, d, self.keyword, param)
def add_data(gb, domain, kf):
    """
    Define the permeability, apertures, boundary conditions
    """
    gb.add_node_props(["param", "is_tangential"])
    tol = 1e-5
    a = 1e-4

    for g, d in gb:
        # Assign aperture
        a_dim = np.power(a, gb.dim_max() - g.dim)
        aperture = np.ones(g.num_cells) * a_dim

        # Effective permeability, scaled with aperture.
        kxx = np.ones(g.num_cells) * np.power(kf,
                                              g.dim < gb.dim_max()) * aperture
        if g.dim == 2:
            perm = pp.SecondOrderTensor(kxx=kxx, kyy=kxx, kzz=1)
        else:
            perm = pp.SecondOrderTensor(kxx=kxx, kyy=1, kzz=1)

        specified_parameters = {"second_order_tensor": perm}
        # Boundaries
        bound_faces = g.tags["domain_boundary_faces"].nonzero()[0]
        if bound_faces.size != 0:
            bound_face_centers = g.face_centers[:, bound_faces]

            left = bound_face_centers[0, :] < domain["xmin"] + tol
            right = bound_face_centers[0, :] > domain["xmax"] - tol

            labels = np.array(["neu"] * bound_faces.size)
            labels[right] = "dir"

            bc_val = np.zeros(g.num_faces)
            bc_val[
                bound_faces[left]] = -a_dim * g.face_areas[bound_faces[left]]
            bc_val[bound_faces[right]] = 1

            bound = pp.BoundaryCondition(g, bound_faces, labels)
            specified_parameters.update({"bc": bound, "bc_values": bc_val})
        else:
            bound = pp.BoundaryCondition(g, np.empty(0), np.empty(0))
            specified_parameters.update({"bc": bound})

        d["is_tangential"] = True
        pp.initialize_default_data(g, d, "flow", specified_parameters)

    # Assign coupling permeability
    for _, d in gb.edges():
        mg = d["mortar_grid"]
        kn = 2 * kf * np.ones(mg.num_cells) / a
        d[pp.PARAMETERS] = pp.Parameters(mg, ["flow"],
                                         [{
                                             "normal_diffusivity": kn
                                         }])
        d[pp.DISCRETIZATION_MATRICES] = {"flow": {}}
Example #7
0
    def test_mpsa(self):
        self.setup()

        g, g_larger = self.g, self.g_larger

        specified_data = {
            "inverter": "python",
        }

        keyword = "mechanics"
        data_small = pp.initialize_default_data(
            g, {}, keyword, specified_parameters=specified_data)

        discr = pp.Mpsa(keyword)
        # Discretization on a small problem
        discr.discretize(g, data_small)

        # Perturb one node
        g_larger.nodes[0, 2] += 0.2
        # Faces that have their geometry changed
        update_faces = np.array([2, 21, 22])

        # Perturb the permeability in some cells on the larger grid
        mu, lmbda = np.ones(g_larger.num_cells), np.ones(g_larger.num_cells)

        high_coeff_cells = np.array([7, 12])
        stiff_larger = pp.FourthOrderTensor(mu, lmbda)

        specified_data_larger = {"fourth_order_tensor": stiff_larger}

        # Do a full discretization on the larger grid
        data_full = pp.initialize_default_data(
            g_larger, {}, keyword, specified_parameters=specified_data_larger)
        discr.discretize(g_larger, data_full)

        # Cells that will be marked as updated, either due to changed parameters or
        # the newly defined topology
        update_cells = np.union1d(self.new_cells, high_coeff_cells)

        updates = {
            "modified_cells": update_cells,
            #            "modified_faces": update_faces,
            "map_cells": self.cell_map,
            "map_faces": self.face_map,
        }

        # Data dictionary for the two-step discretization
        data_partial = pp.initialize_default_data(
            g_larger, {}, keyword, specified_parameters=specified_data_larger)
        data_partial["update_discretization"] = updates

        self._update_and_compare(data_small, data_partial, data_full, g_larger,
                                 [keyword], discr)
Example #8
0
    def test_inv_mass_matrix_1d(self):
        """
        Test the inverse of mass matrix in 1d for a simple geometry
        """
        g = pp.CartGrid(3, 1)
        g.compute_geometry()

        # Mass weight is scaled by aperture 0.01
        specified_parameters = {"mass_weight": 0.5 * 1e-2}
        data = pp.initialize_default_data(g, {}, "flow", specified_parameters)

        discr = pp.MixedInvMassMatrix()
        discr.discretize(g, data)
        lhs, rhs = discr.assemble_matrix_rhs(g, data)

        lhs_known = 600 * np.array(
            [
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
            ]
        )

        self.assertTrue(np.allclose(lhs.toarray(), lhs_known))
        self.assertTrue(np.allclose(rhs, 0))
Example #9
0
    def test_convergence_rt0_2d_iso_simplex_exact(self):

        p_ex = lambda pt: 2 * pt[0, :] - 3 * pt[1, :] - 9

        for i in np.arange(5):
            g = pp.simplex.StructuredTriangleGrid([3 + i] * 2, [1, 1])
            g.compute_geometry()

            kxx = np.ones(g.num_cells)
            perm = pp.SecondOrderTensor(kxx=kxx, kyy=kxx, kzz=1)
            bf = g.get_boundary_faces()
            bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
            bc_val = np.zeros(g.num_faces)
            bc_val[bf] = p_ex(g.face_centers[:, bf])

            solver = pp.RT0(keyword="flow")

            specified_parameters = {
                "bc": bc,
                "bc_values": bc_val,
                "second_order_tensor": perm,
            }
            data = pp.initialize_default_data(g, {}, "flow",
                                              specified_parameters)

            solver.discretize(g, data)
            M, rhs = solver.assemble_matrix_rhs(g, data)

            up = sps.linalg.spsolve(M, rhs)
            p = solver.extract_pressure(g, up, data)
            err = np.sum(np.abs(p - p_ex(g.cell_centers)))

            self.assertTrue(np.isclose(err, 0))
Example #10
0
    def test_upwind_2d_cart_darcy_flux_positive(self):
        g = pp.CartGrid([3, 2], [1, 1])
        g.compute_geometry()

        solver = pp.Upwind()
        dis = solver.darcy_flux(g, [2, 0, 0])

        bf = g.tags["domain_boundary_faces"].nonzero()[0]
        bc = pp.BoundaryCondition(g, bf, bf.size * ["neu"])
        specified_parameters = {"bc": bc, "darcy_flux": dis}
        data = pp.initialize_default_data(g, {}, "transport", specified_parameters)

        solver.discretize(g, data)

        M = solver.assemble_matrix_rhs(g, data)[0].todense()
        deltaT = solver.cfl(g, data)

        M_known = np.array(
            [
                [1, 0, 0, 0, 0, 0],
                [-1, 1, 0, 0, 0, 0],
                [0, -1, 0, 0, 0, 0],
                [0, 0, 0, 1, 0, 0],
                [0, 0, 0, -1, 1, 0],
                [0, 0, 0, 0, -1, 0],
            ]
        )

        deltaT_known = 1 / 12

        rtol = 1e-15
        atol = rtol
        self.assertTrue(np.allclose(M, M_known, rtol, atol))
        self.assertTrue(np.allclose(deltaT, deltaT_known, rtol, atol))
Example #11
0
    def test_upwind_1d_darcy_flux_negative_bc_neu(self):
        g = pp.CartGrid(3, 1)
        g.compute_geometry()

        solver = pp.Upwind()
        dis = solver.darcy_flux(g, [-2, 0, 0])

        bf = g.tags["domain_boundary_faces"].nonzero()[0]
        bc = pp.BoundaryCondition(g, bf, bf.size * ["neu"])
        bc_val = np.array([2, 0, 0, -2]).ravel("F")
        specified_parameters = {"bc": bc, "bc_values": bc_val, "darcy_flux": dis}
        data = pp.initialize_default_data(g, {}, "transport", specified_parameters)

        solver.discretize(g, data)

        M, rhs = solver.assemble_matrix_rhs(g, data)
        deltaT = solver.cfl(g, data)

        M_known = np.array([[0, -2, 0], [0, 2, -2], [0, 0, 2]])
        rhs_known = np.array([-2, 0, 2])
        deltaT_known = 1 / 12

        rtol = 1e-15
        atol = rtol
        self.assertTrue(np.allclose(M.todense(), M_known, rtol, atol))
        self.assertTrue(np.allclose(rhs, rhs_known, rtol, atol))
        self.assertTrue(np.allclose(deltaT, deltaT_known, rtol, atol))
Example #12
0
    def test_upwind_2d_simplex_surf_darcy_flux_negative(self):
        g = pp.StructuredTriangleGrid([2, 1], [1, 1])
        R = pp.map_geometry.rotation_matrix(-np.pi / 5.0, [1, 1, -1])
        g.nodes = np.dot(R, g.nodes)
        g.compute_geometry()

        solver = pp.Upwind()
        dis = solver.darcy_flux(g, np.dot(R, [-1, 0, 0]))

        bf = g.tags["domain_boundary_faces"].nonzero()[0]
        bc = pp.BoundaryCondition(g, bf, bf.size * ["neu"])
        specified_parameters = {"bc": bc, "darcy_flux": dis}
        data = pp.initialize_default_data(g, {}, "transport", specified_parameters)

        solver.discretize(g, data)

        M = solver.assemble_matrix_rhs(g, data)[0].todense()
        deltaT = solver.cfl(g, data)

        M_known = np.array([[1, 0, 0, -1], [-1, 0, 0, 0], [0, 0, 1, 0], [0, 0, -1, 1]])
        deltaT_known = 1 / 6

        rtol = 1e-15
        atol = rtol
        self.assertTrue(np.allclose(M, M_known, rtol, atol))
        self.assertTrue(np.allclose(deltaT, deltaT_known, rtol, atol))
Example #13
0
    def add_data(self, g):
        """
        Define the permeability, apertures, boundary conditions
        """
        # Permeability
        kxx = np.array([self.permeability(*pt) for pt in g.cell_centers.T])
        perm = pp.SecondOrderTensor(kxx)

        # Source term
        source = g.cell_volumes * np.array(
            [self.rhs(*pt) for pt in g.cell_centers.T])

        # Boundaries
        bound_faces = g.tags["domain_boundary_faces"].nonzero()[0]
        bound_face_centers = g.face_centers[:, bound_faces]

        labels = np.array(["dir"] * bound_faces.size)

        bc_val = np.zeros(g.num_faces)
        bc_val[bound_faces] = np.array(
            [self.solution(*pt) for pt in bound_face_centers.T])

        bound = pp.BoundaryCondition(g, bound_faces, labels)
        specified_parameters = {
            "second_order_tensor": perm,
            "source": source,
            "bc": bound,
            "bc_values": bc_val,
        }
        return pp.initialize_default_data(g, {}, "flow", specified_parameters)
Example #14
0
def setup_3d_grid():
    g = pp.CartGrid([2, 2, 2], physdims=[1, 1, 1])
    g.compute_geometry()
    src = np.zeros(g.num_cells)
    src[4] = 1
    data = pp.initialize_default_data(g, {}, "flow", {"source": src})
    return g, data
    def setup(self):
        g = pp.CartGrid([5, 5])
        g.compute_geometry()
        stiffness = pp.FourthOrderTensor(np.ones(g.num_cells),
                                         np.ones(g.num_cells))
        bnd = pp.BoundaryConditionVectorial(g)

        specified_data = {
            "fourth_order_tensor": stiffness,
            "bc": bnd,
            "inverter": "python",
        }
        keyword = "mechanics"
        data = pp.initialize_default_data(g, {},
                                          keyword,
                                          specified_parameters=specified_data)

        discr = pp.Mpsa(keyword)
        discr.discretize(g, data)
        stress = data[pp.DISCRETIZATION_MATRICES][keyword][
            discr.stress_matrix_key]
        bound_stress = data[pp.DISCRETIZATION_MATRICES][keyword][
            discr.bound_stress_matrix_key]

        return g, stiffness, bnd, stress, bound_stress
Example #16
0
def test_symmetry_periodic_pressure_field_2d(method):
    """
    Test that we obtain a symmetric solution accross the periodic boundary.
    The test consider the unit square with periodic boundary conditions
    on the top and bottom boundary. A source is added to the bottom row of
    cells and we test that the solution is periodic.
    Setup, with x denoting the source:
           --------
          |       |
    p = 0 |       | p = 0
          |   x   |
           -------
    """
    # Structured Cartesian grid
    g, kxx = setup_cart_2d(np.array([5, 5]), [1, 1])

    bot_faces = np.argwhere(g.face_centers[1] < 1e-5).ravel()
    top_faces = np.argwhere(g.face_centers[1] > 1 - 1e-5).ravel()

    left_faces = np.argwhere(g.face_centers[0] < 1e-5).ravel()
    right_faces = np.argwhere(g.face_centers[0] > 1 - 1e-5).ravel()

    dir_faces = np.hstack((left_faces, right_faces))

    g.set_periodic_map(np.vstack((bot_faces, top_faces)))

    bound = pp.BoundaryCondition(g, dir_faces, "dir")

    # Solve
    key = "flow"
    d = pp.initialize_default_data(
        g, {}, key, {
            "second_order_tensor": pp.SecondOrderTensor(kxx),
            "bc": bound
        })
    if method == "tpfa":
        discr = pp.Tpfa(key)
    elif method == "mpfa":
        discr = pp.Mpfa(key)
    else:
        assert False

    discr.discretize(g, d)
    matrix_dictionary = d[pp.DISCRETIZATION_MATRICES][key]
    flux, bound_flux = matrix_dictionary["flux"], matrix_dictionary[
        "bound_flux"]

    div = g.cell_faces.T

    a = div * flux

    pr_bound = np.zeros(g.num_faces)
    src = np.zeros(g.num_cells)
    src[2] = 1

    rhs = -div * bound_flux * pr_bound + src
    pr = np.linalg.solve(a.todense(), rhs)

    p_diff = pr[5:15] - np.hstack((pr[-5:], pr[-10:-5]))
    assert np.max(np.abs(p_diff)) < 1e-10
Example #17
0
def _tpfa_matrix(g, perm=None):
    """
    Compute a two-point flux approximation matrix useful related to a call of
    create_partition.

    Parameters
    ----------
    g: the grid
    perm: (optional) permeability, the it is not given unitary tensor is assumed

    Returns
    -------
    out: sparse matrix
        Two-point flux approximation matrix

    """
    if isinstance(g, grid_bucket.GridBucket):
        g = g.get_grids(lambda g_: g_.dim == g.dim_max())[0]

    if perm is None:
        perm = pp.SecondOrderTensor(np.ones(g.num_cells))

    solver = pp.Tpfa("flow")
    specified_parameters = {
        "second_order_tensor": perm,
        "bc": pp.BoundaryCondition(g, np.empty(0), ""),
    }
    data = pp.initialize_default_data(g, {}, "flow", specified_parameters)
    solver.discretize(g, data)
    return solver.assemble_matrix(g, data)
Example #18
0
    def test_upwind_example_2(self, if_export=False):
        #######################
        # Simple 2d upwind problem with implicit Euler scheme in time
        #######################
        T = 1
        Nx, Ny = 10, 1
        g = pp.CartGrid([Nx, Ny], [1, 1])
        g.compute_geometry()

        advect = pp.Upwind("transport")
        dis = advect.darcy_flux(g, [1, 0, 0])

        b_faces = g.get_all_boundary_faces()
        bc = pp.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size)
        bc_val = np.hstack(([1], np.zeros(g.num_faces - 1)))
        specified_parameters = {
            "bc": bc,
            "bc_values": bc_val,
            "darcy_flux": dis
        }
        data = pp.initialize_default_data(g, {}, "transport",
                                          specified_parameters)
        time_step = advect.cfl(g, data)
        data[pp.PARAMETERS]["transport"]["time_step"] = time_step

        advect.discretize(g, data)
        U, rhs = advect.assemble_matrix_rhs(g, data)
        rhs = time_step * rhs
        U = time_step * U
        mass = pp.MassMatrix("transport")
        mass.discretize(g, data)
        M, _ = mass.assemble_matrix_rhs(g, data)

        conc = np.zeros(g.num_cells)

        # Perform an LU factorization to speedup the solver
        IE_solver = sps.linalg.factorized((M + U).tocsc())

        # Loop over the time
        Nt = int(T / time_step)
        time = np.empty(Nt)
        for i in np.arange(Nt):
            # Update the solution
            # Backward and forward substitution to solve the system
            conc = IE_solver(M.dot(conc) + rhs)
            time[i] = time_step * i

        known = np.array([
            0.99969927,
            0.99769441,
            0.99067741,
            0.97352474,
            0.94064879,
            0.88804726,
            0.81498958,
            0.72453722,
            0.62277832,
            0.51725056,
        ])
        assert np.allclose(conc, known)
Example #19
0
    def test_initialize_default_data(self):
        """ Test default flow data initialization with default values.

        initialize_data returns a data dictionary d with default "keyword" Parameters
        stored in d["parameters"].
        """
        data = pp.initialize_default_data(self.g, {}, parameter_type="flow")
        self.check_default_flow_dictionary(data[pp.PARAMETERS]["flow"])
Example #20
0
    def _matrix(self, g, perm, bc):
        solver = pp.RT0(keyword="flow")

        data = pp.initialize_default_data(g, {}, "flow", {
            "second_order_tensor": perm,
            "bc": bc
        })
        solver.discretize(g, data)

        return solver.assemble_matrix(g, data).todense()
Example #21
0
 def test_matrix_rhs(self):
     g_list = setup_grids.setup_2d()
     kw = "mechanics"
     for g in g_list:
         solver = pp.numerics.fv.mpsa.Mpsa(kw)
         data = pp.initialize_default_data(g, {}, kw)
         A, b = solver.assemble_matrix_rhs(g, data)
         self.assertTrue(
             np.all(A.shape == (g.dim * g.num_cells, g.dim * g.num_cells)))
         self.assertTrue(b.size == g.dim * g.num_cells)
Example #22
0
def setup_2d_1d(nx, simplex_grid=False):
    if not simplex_grid:
        frac1 = np.array([[0.2, 0.8], [0.5, 0.5]])
        frac2 = np.array([[0.5, 0.5], [0.8, 0.2]])
        fracs = [frac1, frac2]

        gb = pp.meshing.cart_grid(fracs, nx, physdims=[1, 1])
    else:
        p = np.array([[0.2, 0.8, 0.5, 0.5], [0.5, 0.5, 0.8, 0.2]])
        e = np.array([[0, 2], [1, 3]])
        domain = {"xmin": 0, "ymin": 0, "xmax": 1, "ymax": 1}
        network = pp.FractureNetwork2d(p, e, domain)
        mesh_size = 0.08
        mesh_kwargs = {"mesh_size_frac": mesh_size, "mesh_size_min": mesh_size / 20}

        gb = network.mesh(mesh_kwargs)

    gb.compute_geometry()
    gb.assign_node_ordering()
    aperture = 0.01 / np.max(nx)
    for g, d in gb:
        a = np.power(aperture, gb.dim_max() - g.dim) * np.ones(g.num_cells)
        kxx = np.ones(g.num_cells) * a
        perm = pp.SecondOrderTensor(kxx)
        specified_parameters = {"second_order_tensor": perm}
        if g.dim == 2:
            bound_faces = g.tags["domain_boundary_faces"].nonzero()[0]
            bound = pp.BoundaryCondition(
                g, bound_faces.ravel("F"), ["dir"] * bound_faces.size
            )
            bc_val = np.zeros(g.num_faces)
            bc_val[bound_faces] = g.face_centers[1, bound_faces]
            specified_parameters.update({"bc": bound, "bc_values": bc_val})

        pp.initialize_default_data(g, d, "flow", specified_parameters)

    for e, d in gb.edges():
        gl, _ = gb.nodes_of_edge(e)
        mg = d["mortar_grid"]
        kn = 1.0 / aperture
        d[pp.PARAMETERS] = pp.Parameters(mg, ["flow"], [{"normal_diffusivity": kn}])
        d[pp.DISCRETIZATION_MATRICES] = {"flow": {}}
    return gb
Example #23
0
    def test_upwind_example_1(self, if_export=False):
        #######################
        # Simple 2d upwind problem with explicit Euler scheme in time
        #######################
        T = 1
        Nx, Ny = 4, 1
        g = pp.CartGrid([Nx, Ny], [1, 1])
        g.compute_geometry()

        advect = pp.Upwind("transport")
        dis = advect.darcy_flux(g, [1, 0, 0])

        b_faces = g.get_all_boundary_faces()
        bc = pp.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size)
        bc_val = np.hstack(([1], np.zeros(g.num_faces - 1)))
        specified_parameters = {
            "bc": bc,
            "bc_values": bc_val,
            "darcy_flux": dis
        }
        data = pp.initialize_default_data(g, {}, "transport",
                                          specified_parameters)
        time_step = advect.cfl(g, data)
        data[pp.PARAMETERS]["transport"]["time_step"] = time_step

        advect.discretize(g, data)

        U, rhs = advect.assemble_matrix_rhs(g, data)
        rhs = time_step * rhs
        U = time_step * U
        OF = advect.outflow(g, data)
        mass = pp.MassMatrix("transport")
        mass.discretize(g, data)
        M, _ = mass.assemble_matrix_rhs(g, data)

        conc = np.zeros(g.num_cells)

        M_minus_U = M - U
        inv_mass = pp.InvMassMatrix("transport")
        inv_mass.discretize(g, data)
        invM, _ = inv_mass.assemble_matrix_rhs(g, data)

        # Loop over the time
        Nt = int(T / time_step)
        time = np.empty(Nt)
        production = np.zeros(Nt)
        for i in np.arange(Nt):

            # Update the solution
            production[i] = np.sum(OF.dot(conc))
            conc = invM.dot((M_minus_U).dot(conc) + rhs)
            time[i] = time_step * i

        known = 1.09375
        assert np.sum(production) == known
Example #24
0
def test_fv_cart_2d_periodic(method):
    """ Apply TPFA and MPFA on a periodic Cartesian grid, should obtain Laplacian stencil."""

    # Set up 3 X 3 Cartesian grid
    nx = np.array([3, 3])
    g = pp.CartGrid(nx)
    g.compute_geometry()

    kxx = np.ones(g.num_cells)
    perm = pp.SecondOrderTensor(kxx)

    left_faces = [0, 4, 8, 12, 13, 14]
    right_faces = [3, 7, 11, 21, 22, 23]
    periodic_face_map = np.vstack((left_faces, right_faces))
    g.set_periodic_map(periodic_face_map)

    bound = pp.BoundaryCondition(g)

    key = "flow"
    d = pp.initialize_default_data(g, {}, key, {
        "second_order_tensor": perm,
        "bc": bound
    })

    if method == "tpfa":
        discr = pp.Tpfa(key)
    elif method == "mpfa":
        discr = pp.Mpfa(key)
    else:
        assert False

    discr.discretize(g, d)
    matrix_dictionary = d[pp.DISCRETIZATION_MATRICES][key]
    trm, bound_flux = matrix_dictionary["flux"], matrix_dictionary[
        "bound_flux"]
    div = g.cell_faces.T
    a = div * trm
    b = -(div * bound_flux).A

    # Create laplace matrix
    A_lap = np.array([
        [4.0, -1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0],
        [-1.0, 4.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0],
        [-1.0, -1.0, 4.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0],
        [-1.0, 0.0, 0.0, 4.0, -1.0, -1.0, -1.0, 0.0, 0.0],
        [0.0, -1.0, 0.0, -1.0, 4.0, -1.0, 0.0, -1.0, 0.0],
        [0.0, 0.0, -1.0, -1.0, -1.0, 4.0, 0.0, 0.0, -1.0],
        [-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 4.0, -1.0, -1.0],
        [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, 4.0, -1.0],
        [0.0, 0.0, -1.0, 0.0, 0.0, -1.0, -1.0, -1.0, 4.0],
    ])

    assert np.allclose(a.A, A_lap)
    assert np.allclose(b, 0)
    return a
    def _matrix(self, g, perm, bc, vect):
        solver = pp.MVEM(keyword="flow")

        data = pp.initialize_default_data(
            g,
            {},
            "flow",
            {"second_order_tensor": perm, "bc": bc, "vector_source": vect},
        )
        solver.discretize(g, data)
        return solver.assemble_matrix_rhs(g, data)[1]
Example #26
0
    def test_convergence_rt0_2d_iso_simplex(self):

        a = 8 * np.pi**2
        rhs_ex = lambda pt: np.multiply(np.sin(2 * np.pi * pt[0, :]),
                                        np.sin(2 * np.pi * pt[1, :]))
        p_ex = lambda pt: rhs_ex(pt) / a

        errs_known = np.array([
            0.00128247705764,
            0.000770088925769,
            0.00050939369071,
            0.000360006145403,
            0.000267209318912,
        ])

        for i, err_known in zip(np.arange(5), errs_known):
            g = pp.simplex.StructuredTriangleGrid([3 + i] * 2, [1, 1])
            g.compute_geometry()

            kxx = np.ones(g.num_cells)
            perm = pp.SecondOrderTensor(kxx=kxx, kyy=kxx, kzz=1)
            bf = g.get_boundary_faces()
            bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
            bc_val = np.zeros(g.num_faces)
            bc_val[bf] = p_ex(g.face_centers[:, bf])
            # Minus sign to move to rhs
            source = np.multiply(g.cell_volumes, rhs_ex(g.cell_centers))

            solver = pp.RT0(keyword="flow")
            solver_rhs = pp.DualScalarSource(keyword="flow")

            specified_parameters = {
                "bc": bc,
                "bc_values": bc_val,
                "second_order_tensor": perm,
                "source": source,
            }
            data = pp.initialize_default_data(g, {}, "flow",
                                              specified_parameters)

            solver.discretize(g, data)
            solver_rhs.discretize(g, data)

            M, rhs_bc = solver.assemble_matrix_rhs(g, data)
            _, rhs = solver_rhs.assemble_matrix_rhs(g, data)

            up = sps.linalg.spsolve(M, rhs_bc + rhs)
            p = solver.extract_pressure(g, up, data)
            err = np.sqrt(
                np.sum(
                    np.multiply(g.cell_volumes,
                                np.power(p - p_ex(g.cell_centers), 2))))
            self.assertTrue(np.isclose(err, err_known))
Example #27
0
def setup_2d_1d(nx, simplex_grid=False):
    if not simplex_grid:
        mesh_args = nx
    else:
        mesh_size = 0.08
        mesh_args = {
            "mesh_size_frac": mesh_size,
            "mesh_size_min": mesh_size / 20
        }

    end_x = [0.2, 0.8]
    end_y = [0.8, 0.2]
    gb, _ = pp.grid_buckets_2d.two_intersecting(mesh_args, end_x, end_y,
                                                simplex_grid)
    aperture = 0.01 / np.max(nx)
    for g, d in gb:
        a = np.power(aperture, gb.dim_max() - g.dim) * np.ones(g.num_cells)
        kxx = np.ones(g.num_cells) * a
        perm = pp.SecondOrderTensor(kxx)
        specified_parameters = {"second_order_tensor": perm}
        if g.dim == 2:
            bound_faces = g.tags["domain_boundary_faces"].nonzero()[0]
            bound = pp.BoundaryCondition(g, bound_faces.ravel("F"),
                                         ["dir"] * bound_faces.size)
            bc_val = np.zeros(g.num_faces)
            bc_val[bound_faces] = g.face_centers[1, bound_faces]
            specified_parameters.update({"bc": bound, "bc_values": bc_val})

        pp.initialize_default_data(g, d, "flow", specified_parameters)

    for e, d in gb.edges():
        gl, _ = gb.nodes_of_edge(e)
        mg = d["mortar_grid"]
        kn = 1.0 / aperture
        d[pp.PARAMETERS] = pp.Parameters(mg, ["flow"],
                                         [{
                                             "normal_diffusivity": kn
                                         }])
        d[pp.DISCRETIZATION_MATRICES] = {"flow": {}}
    return gb
Example #28
0
    def test_convergence_rt0_2d_ani_simplex(self):

        rhs_ex = lambda pt: 14
        p_ex = (lambda pt: 2 * np.power(pt[0, :], 2) - 6 * np.power(
            pt[1, :], 2) + np.multiply(pt[0, :], pt[1, :]))

        errs_known = np.array([
            0.014848639601,
            0.00928479234915,
            0.00625096095775,
            0.00446722560521,
            0.00334170283883,
        ])

        for i, err_known in zip(np.arange(5), errs_known):
            g = pp.simplex.StructuredTriangleGrid([3 + i] * 2, [1, 1])
            g.compute_geometry()

            kxx = 2 * np.ones(g.num_cells)
            kxy = np.ones(g.num_cells)
            perm = pp.SecondOrderTensor(kxx=kxx, kyy=kxx, kxy=kxy, kzz=1)
            bf = g.get_boundary_faces()
            bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
            bc_val = np.zeros(g.num_faces)
            bc_val[bf] = p_ex(g.face_centers[:, bf])
            # Minus sign to move to rhs
            source = np.multiply(g.cell_volumes, rhs_ex(g.cell_centers))

            solver = pp.RT0(keyword="flow")
            solver_rhs = pp.DualScalarSource(keyword="flow")

            specified_parameters = {
                "bc": bc,
                "bc_values": bc_val,
                "second_order_tensor": perm,
                "source": source,
            }
            data = pp.initialize_default_data(g, {}, "flow",
                                              specified_parameters)

            solver.discretize(g, data)
            solver_rhs.discretize(g, data)
            M, rhs_bc = solver.assemble_matrix_rhs(g, data)
            _, rhs = solver_rhs.assemble_matrix_rhs(g, data)

            up = sps.linalg.spsolve(M, rhs_bc + rhs)
            p = solver.extract_pressure(g, up, data)
            err = np.sqrt(
                np.sum(
                    np.multiply(g.cell_volumes,
                                np.power(p - p_ex(g.cell_centers), 2))))
            self.assertTrue(np.isclose(err, err_known))
    def test_bound_cell_node_keyword(self):
        # Compute update for a single cell on the boundary
        g, perm, bnd, flux, bound_flux, vector_source = self.setup()

        # cell = 10
        nodes_of_cell = np.array([12, 13, 18, 19])
        faces_of_cell = np.array([12, 13, 40, 45])
        specified_data = {
            "second_order_tensor": perm,
            "bc": bnd,
            "inverter": "python",
            "specified_nodes": nodes_of_cell,
        }

        keyword = "flow"
        data = pp.initialize_default_data(g, {},
                                          keyword,
                                          specified_parameters=specified_data)

        discr = pp.Mpfa(keyword)
        discr.discretize(g, data)

        partial_flux = data[pp.DISCRETIZATION_MATRICES][keyword][
            discr.flux_matrix_key]
        partial_bound = data[pp.DISCRETIZATION_MATRICES][keyword][
            discr.bound_flux_matrix_key]
        partial_vector_source = data[pp.DISCRETIZATION_MATRICES][keyword][
            discr.vector_source_matrix_key]

        active_faces = data[pp.PARAMETERS][keyword]["active_faces"]

        self.assertTrue(faces_of_cell.size == active_faces.size)
        self.assertTrue(
            np.all(np.sort(faces_of_cell) == np.sort(active_faces)))

        diff_flux = (flux - partial_flux).todense()
        diff_bound = (bound_flux - partial_bound).todense()
        diff_vc = (vector_source - partial_vector_source).todense()

        self.assertTrue(np.max(np.abs(diff_flux[faces_of_cell])) == 0)
        self.assertTrue(np.max(np.abs(diff_bound[faces_of_cell])) == 0)
        self.assertTrue(np.max(np.abs(diff_vc[faces_of_cell])) == 0)

        # Only the faces of the central cell should be zero
        pp.fvutils.zero_out_sparse_rows(partial_flux, faces_of_cell)
        pp.fvutils.zero_out_sparse_rows(partial_bound, faces_of_cell)
        pp.fvutils.zero_out_sparse_rows(partial_vector_source, faces_of_cell)

        self.assertTrue(np.max(np.abs(partial_flux.data)) == 0)
        self.assertTrue(np.max(np.abs(partial_bound.data)) == 0)
        self.assertTrue(np.max(np.abs(partial_vector_source.data)) == 0)
Example #30
0
def test_periodic_pressure_field_2d(method):
    """
    Test that TPFA approximate an analytical periodic solution by imposing
    periodic boundary conditions to the bottom and top faces of the unit square.
    """
    # Structured Cartesian grid
    g, kxx = setup_cart_2d(np.array([10, 10]), [1, 1])

    bot_faces = np.argwhere(g.face_centers[1] < 1e-5).ravel()
    top_faces = np.argwhere(g.face_centers[1] > 1 - 1e-5).ravel()

    left_faces = np.argwhere(g.face_centers[0] < 1e-5).ravel()
    right_faces = np.argwhere(g.face_centers[0] > 1 - 1e-5).ravel()

    dir_faces = np.hstack((left_faces, right_faces))

    g.set_periodic_map(np.vstack((bot_faces, top_faces)))

    bound = pp.BoundaryCondition(g, dir_faces, "dir")

    # Solve
    key = "flow"
    d = pp.initialize_default_data(
        g, {}, key, {
            "second_order_tensor": pp.SecondOrderTensor(kxx),
            "bc": bound
        })
    if method == "tpfa":
        discr = pp.Tpfa(key)
    elif method == "mpfa":
        discr = pp.Mpfa(key)
    else:
        assert False
    discr.discretize(g, d)
    matrix_dictionary = d[pp.DISCRETIZATION_MATRICES][key]
    flux, bound_flux = matrix_dictionary["flux"], matrix_dictionary[
        "bound_flux"]

    div = g.cell_faces.T

    a = div * flux

    pr_bound, pr_cell, src = setup_periodic_pressure_field(g, kxx)

    rhs = -div * bound_flux * pr_bound + src * g.cell_volumes
    pr = np.linalg.solve(a.todense(), rhs)

    p_diff = pr - pr_cell

    assert np.max(np.abs(p_diff)) < 0.06