Beispiel #1
0
    def test_dual_rt0_1d_iso_line(self):
        g = pp.structured.CartGrid(3, 1)
        R = cg.rot(np.pi / 6., [0, 0, 1])
        g.nodes = np.dot(R, g.nodes)
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx, kyy=1, kzz=1)
        perm.rotate(R)

        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()

        # Matrix computed with an already validated code
        M_known = np.matrix(
            [
                [0.11111111, 0.05555556, 0., 0., 1., 0., 0.],
                [0.05555556, 0.22222222, 0.05555556, 0., -1., 1., 0.],
                [0., 0.05555556, 0.22222222, 0.05555556, 0., -1., 1.],
                [0., 0., 0.05555556, 0.11111111, 0., 0., -1.],
                [1., -1., 0., 0., 0., 0., 0.],
                [0., 1., -1., 0., 0., 0., 0.],
                [0., 0., 1., -1., 0., 0., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #2
0
    def test_rt0_1d_ani(self):
        g = pp.structured.CartGrid(3, 1)
        g.compute_geometry()

        kxx = 1. / (np.sin(g.cell_centers[0, :]) + 1)
        perm = pp.SecondOrderTensor(3, kxx, kyy=1, kzz=1)
        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()

        M_known = np.matrix(
            [
                [0.12954401, 0.06477201, 0., 0., 1., 0., 0.],
                [0.06477201, 0.29392463, 0.08219031, 0., -1., 1., 0.],
                [0., 0.08219031, 0.3577336, 0.09667649, 0., -1., 1.],
                [0., 0., 0.09667649, 0.19335298, 0., 0., -1.],
                [1., -1., 0., 0., 0., 0., 0.],
                [0., 1., -1., 0., 0., 0., 0.],
                [0., 0., 1., -1., 0., 0., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #3
0
    def test_rt0_1d_iso(self):
        g = pp.structured.CartGrid(3, 1)
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx, kyy=1, kzz=1)
        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])

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

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()

        M_known = np.matrix(
            [
                [0.11111111, 0.05555556, 0., 0., 1., 0., 0.],
                [0.05555556, 0.22222222, 0.05555556, 0., -1., 1., 0.],
                [0., 0.05555556, 0.22222222, 0.05555556, 0., -1., 1.],
                [0., 0., 0.05555556, 0.11111111, 0., 0., -1.],
                [1., -1., 0., 0., 0., 0., 0.],
                [0., 1., -1., 0., 0., 0., 0.],
                [0., 0., 1., -1., 0., 0., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #4
0
 def run_RT0(self, gb):
     key = "flow"
     method = pp.RT0(key)
     self._solve(gb, method, key)
     for g, d in gb:
         d[pp.STATE]["darcy_flux"] = d[pp.STATE]["pressure"][:g.num_faces]
         d[pp.STATE]["pressure"] = d[pp.STATE]["pressure"][g.num_faces:]
Beispiel #5
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(3, 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(physics="flow")

            param = pp.Parameters(g)
            param.set_tensor(solver, perm)
            param.set_bc(solver, bc)
            param.set_bc_val(solver, bc_val)
            M, rhs = solver.matrix_rhs(g, {"param": param})

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

            self.assertTrue(np.isclose(err, 0))
Beispiel #6
0
    def test_rt0_2d_ani_simplex(self):
        g = pp.simplex.StructuredTriangleGrid([1, 1], [1, 1])
        g.compute_geometry()

        al = np.square(g.cell_centers[1, :]) + np.square(g.cell_centers[0, :]) + 1
        kxx = (np.square(g.cell_centers[0, :]) + 1) / al
        kyy = (np.square(g.cell_centers[1, :]) + 1) / al
        kxy = np.multiply(g.cell_centers[0, :], g.cell_centers[1, :]) / al

        perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kyy, kxy=kxy, kzz=1)

        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()

        # Matrix computed with an already validated code
        M_known = np.matrix(
            [
                [0.39814815, 0., -0.0462963, -0.15740741, 0., -1., 0.],
                [0., 0.39814815, 0.0462963, 0., -0.15740741, 0., -1.],
                [-0.0462963, 0.0462963, 0.46296296, 0.00925926, -0.00925926, -1., 1.],
                [-0.15740741, 0., 0.00925926, 0.34259259, 0., -1., 0.],
                [0., -0.15740741, -0.00925926, 0., 0.34259259, 0., -1.],
                [-1., 0., -1., -1., 0., 0., 0.],
                [0., -1., 1., 0., -1., 0., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #7
0
    def test_rt0_2d_iso_simplex_surf(self):
        g = pp.simplex.StructuredTriangleGrid([1, 1], [1, 1])
        R = cg.rot(-np.pi / 4., [1, 1, -1])
        g.nodes = np.dot(R, g.nodes)
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kxx, kzz=1)
        perm.rotate(R)

        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()

        # Matrix computed with an already validated code
        M_known = np.matrix(
            [
                [0.33333333, 0., 0., -0.16666667, 0., -1., 0.],
                [0., 0.33333333, 0., 0., -0.16666667, 0., -1.],
                [0., 0., 0.33333333, 0., 0., -1., 1.],
                [-0.16666667, 0., 0., 0.33333333, 0., -1., 0.],
                [0., -0.16666667, 0., 0., 0.33333333, 0., -1.],
                [-1., 0., -1., -1., 0., 0., 0.],
                [0., -1., 1., 0., -1., 0., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        # We test only the mass-Hdiv part
        self.assertTrue(np.allclose(M, M_known))
Beispiel #8
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))
    def __init__(self, gb, folder, tol):

        self.model = "flow"
        self.gb = gb
        self.data = None
        self.assembler = None

        # discretization operator name
        self.discr_name = "flux"
        self.discr = pp.RT0(self.model)

        self.mass_name = "mass"
        self.mass = pp.MixedMassMatrix(self.model)

        self.coupling_name = self.discr_name + "_coupling"
        self.coupling = pp.RobinCoupling(self.model, self.discr)

        self.source_name = "source"
        self.source = pp.DualScalarSource(self.model)

        # master variable name
        self.variable = "flow_variable"
        self.mortar = "lambda_" + self.variable

        # post process variables
        self.pressure = "pressure"
        self.flux = "darcy_flux"  # it has to be this one
        self.P0_flux = "P0_darcy_flux"

        # tolerance
        self.tol = tol

        # exporter
        self.save = pp.Exporter(self.gb, "solution", folder=folder)
Beispiel #10
0
def homo_mortar(g):
    return {
        "scheme": pp.RT0("flow"),
        "dof": {
            "cells": 1,
            "faces": 1
        },
        "label": "homo_mortar"
    }
Beispiel #11
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()
Beispiel #12
0
def solve_rt0(gb, folder, discr_3d=None):
    # Choose and define the solvers and coupler
    flow_discretization = pp.RT0("flow")
    source_discretization = pp.DualScalarSource("flow")
    run_flow(gb,
             flow_discretization,
             source_discretization,
             folder,
             is_FV=False,
             discr_3d=discr_3d)
Beispiel #13
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))
Beispiel #14
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(3, 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])
            source = np.multiply(g.cell_volumes, rhs_ex(g.cell_centers))

            solver = pp.RT0(physics="flow")
            solver_rhs = pp.DualSource(physics="flow")

            param = pp.Parameters(g)
            param.set_tensor("flow", perm)
            param.set_bc("flow", bc)
            param.set_bc_val("flow", bc_val)
            param.set_source("flow", source)

            M, rhs_bc = solver.matrix_rhs(g, {"param": param})
            _, rhs = solver_rhs.matrix_rhs(g, {"param": param})

            up = sps.linalg.spsolve(M, rhs_bc + rhs)
            p = solver.extract_p(g, up)
            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))
Beispiel #15
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))
Beispiel #16
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(3, 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])
            source = np.multiply(g.cell_volumes, rhs_ex(g.cell_centers))

            solver = pp.RT0(physics="flow")
            solver_rhs = pp.DualSource(physics="flow")

            param = pp.Parameters(g)
            param.set_tensor("flow", perm)
            param.set_bc("flow", bc)
            param.set_bc_val("flow", bc_val)
            param.set_source("flow", source)

            M, rhs_bc = solver.matrix_rhs(g, {"param": param})
            _, rhs = solver_rhs.matrix_rhs(g, {"param": param})

            up = sps.linalg.spsolve(M, rhs_bc + rhs)
            p = solver.extract_p(g, up)
            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 _matrix(self, g, perm, bc, vect):
        solver = pp.RT0(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]
    def test_convergence_rt0_2d_iso_simplex_exact(self):

        p_ex = lambda pt: 2 * pt[0, :] - 3 * pt[1, :] - 9
        u_ex = np.array([-1, 4, 0])

        for i in np.arange(5):
            g = pp.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])
            vect = np.vstack((g.cell_volumes, g.cell_volumes,
                              np.zeros(g.num_cells))).ravel(order="F")

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

            specified_parameters = {
                "bc": bc,
                "bc_values": bc_val,
                "second_order_tensor": perm,
                "vector_source": vect,
            }
            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))

            _ = data[pp.DISCRETIZATION_MATRICES]["flow"][
                solver.vector_proj_key]
            u = solver.extract_flux(g, up, data)
            P0u = solver.project_flux(g, u, data)
            err = np.sum(
                np.abs(P0u -
                       np.tile(u_ex, g.num_cells).reshape((3, -1), order="F")))

            self.assertTrue(np.isclose(err, 0))
Beispiel #19
0
def hete1(g):
    if g.dim == 2:
        scheme = {
            "scheme": pp.RT0("flow"),
            "dof": {
                "cells": 1,
                "faces": 1
            },
            "label": "hete1"
        }
    else:
        scheme = {
            "scheme": pp.Tpfa("flow"),
            "dof": {
                "cells": 1
            },
            "label": "hete1"
        }
    return scheme
Beispiel #20
0
    def test_rt0_3d(self):

        g = pp.simplex.StructuredTetrahedralGrid([1, 1, 1], [1, 1, 1])
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kxx, kzz=kxx)

        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()
        M_known = matrix_for_test_rt0_3d()

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #21
0
    def test_rt0_2d_triangle(self):

        dim = 2
        nodes = np.array([[0, 1, 0], [0, 0, 1], [0, 0, 0]])

        indices = [0, 1, 1, 2, 2, 0]
        indptr = [0, 2, 4, 6]
        face_nodes = sps.csc_matrix(([True] * 6, indices, indptr))
        cell_faces = sps.csc_matrix([[1], [1], [1]])
        name = "test"

        g = pp.Grid(dim, nodes, face_nodes, cell_faces, name)
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kxx, kzz=1)

        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()

        # Matrix computed with an already validated code
        M_known = np.matrix(
            [
                [0.33333333, 0., -0.16666667, -1.],
                [0., 0.16666667, 0., -1.],
                [-0.16666667, 0., 0.33333333, -1.],
                [-1., -1., -1., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #22
0
    def test_rt0_tetra(self):

        dim = 3
        nodes = np.array([[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])

        indices = [0, 2, 1, 1, 2, 3, 2, 0, 3, 3, 0, 1]
        indptr = [0, 3, 6, 9, 12]
        face_nodes = sps.csc_matrix(([True] * 12, indices, indptr))
        cell_faces = sps.csc_matrix([[1], [1], [1], [1]])
        name = "test"

        g = pp.Grid(dim, nodes, face_nodes, cell_faces, name)
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kxx, kzz=kxx)

        bf = g.get_boundary_faces()
        bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"])
        solver = pp.RT0(physics="flow")

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        M = solver.matrix(g, {"param": param}).todense()
        M_known = np.matrix(
            [
                [0.53333333, 0.03333333, -0.13333333, -0.13333333, -1.],
                [0.03333333, 0.2, 0.03333333, 0.03333333, -1.],
                [-0.13333333, 0.03333333, 0.53333333, -0.13333333, -1.],
                [-0.13333333, 0.03333333, -0.13333333, 0.53333333, -1.],
                [-1., -1., -1., -1., 0.],
            ]
        )

        self.assertTrue(np.allclose(M, M.T))
        self.assertTrue(np.allclose(M, M_known))
Beispiel #23
0
def flow(gb, param, bc_flag):

    model = "flow"

    model_data = data_flow(gb, model, param, bc_flag)

    # discretization operator name
    flux_id = "flux"

    # master variable name
    variable = "flow_variable"
    mortar = "lambda_" + variable

    # post process variables
    pressure = "pressure"
    flux = "darcy_flux"  # it has to be this one

    # save variable name for the advection-diffusion problem
    param["pressure"] = pressure
    param["flux"] = flux
    param["mortar_flux"] = mortar

    # define the dof and discretization for the grids
    for g, d in gb:
        d[pp.PRIMARY_VARIABLES] = {variable: {"cells": 1, "faces": 1}}
        if g.dim == gb.dim_max():
            discr = pp.RT0(model_data)
        else:
            discr = RT0Multilayer(model_data)
        d[pp.DISCRETIZATION] = {variable: {flux_id: discr}}

    # define the interface terms to couple the grids
    for e, d in gb.edges():
        g_slave, g_master = gb.nodes_of_edge(e)
        d[pp.PRIMARY_VARIABLES] = {mortar: {"cells": 1}}

        # retrive the discretization of the master and slave grids
        discr_master = gb.node_props(g_master,
                                     pp.DISCRETIZATION)[variable][flux_id]
        discr_slave = gb.node_props(g_slave,
                                    pp.DISCRETIZATION)[variable][flux_id]

        if g_master.dim == gb.dim_max():
            # classical 2d-1d/3d-2d coupling condition
            coupling = pp.RobinCoupling(model_data, discr_master, discr_slave)

            d[pp.COUPLING_DISCRETIZATION] = {
                flux: {
                    g_slave: (variable, flux_id),
                    g_master: (variable, flux_id),
                    e: (mortar, coupling),
                }
            }
        elif g_master.dim < gb.dim_max():
            # the multilayer coupling condition
            coupling = RobinCouplingMultiLayer(model_data, discr_master,
                                               discr_slave)

            d[pp.COUPLING_DISCRETIZATION] = {
                flux: {
                    g_slave: (variable, flux_id),
                    g_master: (variable, flux_id),
                    e: (mortar, coupling),
                }
            }

    # solution of the darcy problem
    assembler = pp.Assembler()

    logger.info("Assemble the flow problem")
    A, b, block_dof, full_dof = assembler.assemble_matrix_rhs(gb)
    logger.info("done")

    logger.info("Solve the linear system")
    x = sps.linalg.spsolve(A, b)
    logger.info("done")

    logger.info("Variable post-process")
    assembler.distribute_variable(gb, x, block_dof, full_dof)
    for g, d in gb:
        d[pressure] = discr.extract_pressure(g, d[variable], d)
        d[flux] = discr.extract_flux(g, d[variable], d)

    # export the P0 flux reconstruction
    P0_flux = "P0_flux"
    param["P0_flux"] = P0_flux
    pp.project_flux(gb, discr, flux, P0_flux, mortar)

    # identification of layer and fault
    for g, d in gb:
        # save the identification of the fault
        if "fault" in g.name:
            d["fault"] = np.ones(g.num_cells)
            d["layer"] = np.zeros(g.num_cells)
        # save the identification of the layer
        elif "layer" in g.name:
            d["fault"] = np.zeros(g.num_cells)
            half_cells = int(g.num_cells / 2)
            d["layer"] = np.hstack(
                (np.ones(half_cells), 2 * np.ones(half_cells)))
        # save zero for the other cases
        else:
            d["fault"] = np.zeros(g.num_cells)
            d["layer"] = np.zeros(g.num_cells)

    save = pp.Exporter(gb, "solution", folder=param["folder"])
    save.write_vtk([pressure, P0_flux, "fault", "layer"])

    logger.info("done")
    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
        u_ex_0 = (lambda pt: np.multiply(-np.cos(2 * np.pi * pt[
            0, :]), np.sin(2 * np.pi * pt[1, :])) * 2 * np.pi / a + 1)
        u_ex_1 = (lambda pt: np.multiply(-np.sin(2 * np.pi * pt[
            0, :]), np.cos(2 * np.pi * pt[1, :])) * 2 * np.pi / a)

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

        u_errs_known = np.array([
            0.0244256176861958,
            0.016806807988931607,
            0.012859109258624908,
            0.010445238111710818,
            0.008811844361691242,
        ])

        for i, p_err_known, u_err_known in zip(np.arange(5), p_errs_known,
                                               u_errs_known):
            g = pp.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))
            vect = np.vstack((g.cell_volumes, np.zeros(g.num_cells),
                              np.zeros(g.num_cells))).ravel(order="F")

            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,
                "vector_source": vect,
            }
            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, p_err_known))

            _ = data[pp.DISCRETIZATION_MATRICES]["flow"][
                solver.vector_proj_key]
            u = solver.extract_flux(g, up, data)
            P0u = solver.project_flux(g, u, data)
            uu_ex_0 = u_ex_0(g.cell_centers)
            uu_ex_1 = u_ex_1(g.cell_centers)
            uu_ex_2 = np.zeros(g.num_cells)
            uu_ex = np.vstack((uu_ex_0, uu_ex_1, uu_ex_2))
            err = np.sqrt(
                np.sum(
                    np.multiply(g.cell_volumes,
                                np.sum(np.power(P0u - uu_ex, 2), axis=0))))
            self.assertTrue(np.isclose(err, u_err_known))
    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, :]))
        u_ex_0 = lambda pt: -9 * pt[0, :] + 10 * pt[1, :] + 4
        u_ex_1 = lambda pt: -6 * pt[0, :] + 23 * pt[1, :] + 5

        p_errs_known = np.array([
            0.014848639601,
            0.00928479234915,
            0.00625096095775,
            0.00446722560521,
            0.00334170283883,
        ])
        u_errs_known = np.array([
            1.7264059760345314,
            1.34164231163404,
            1.0925566034251668,
            0.9198698104736419,
            0.7936243780450764,
        ])

        for i, p_err_known, u_err_known in zip(np.arange(5), p_errs_known,
                                               u_errs_known):
            g = pp.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))
            vect = np.vstack((g.cell_volumes, 2 * g.cell_volumes,
                              np.zeros(g.num_cells))).ravel(order="F")

            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,
                "vector_source": vect,
            }
            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, p_err_known))

            _ = data[pp.DISCRETIZATION_MATRICES]["flow"][
                solver.vector_proj_key]
            u = solver.extract_flux(g, up, data)
            P0u = solver.project_flux(g, u, data)
            uu_ex_0 = u_ex_0(g.cell_centers)
            uu_ex_1 = u_ex_1(g.cell_centers)
            uu_ex_2 = np.zeros(g.num_cells)
            uu_ex = np.vstack((uu_ex_0, uu_ex_1, uu_ex_2))
            err = np.sqrt(
                np.sum(
                    np.multiply(g.cell_volumes,
                                np.sum(np.power(P0u - uu_ex, 2), axis=0))))
            self.assertTrue(np.isclose(err, u_err_known))
Beispiel #26
0
    def test_rt0_2d_iso_simplex_mixed_bc(self):
        g = pp.simplex.StructuredTriangleGrid([2, 2], [1, 1])
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(kxx=kxx, kyy=kxx, kzz=1)

        tol = 1e-6
        bf = g.tags["domain_boundary_faces"].nonzero()[0]
        bf_centers = g.face_centers[:, bf]
        left = bf_centers[0, :] < 0 + tol
        right = bf_centers[0, :] > 1 - tol

        labels = np.array(["neu"] * bf.size)
        labels[left] = "rob"
        labels[right] = "dir"

        bc = pp.BoundaryCondition(g, bf, labels)
        bc.robin_weight[bf[left]] = 2

        bc_val = np.zeros(g.num_faces)
        bc_val[bf[left]] = 3

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

        specified_parameters = {
            "bc": bc,
            "second_order_tensor": perm,
            "bc_values": bc_val,
        }
        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)
        u = solver.extract_flux(g, up, data)
        P0u = solver.project_flux(g, u, data)

        p_ex = 1 - g.cell_centers[0, :]
        P0u_ex = np.vstack((np.ones(g.num_cells), np.zeros(g.num_cells),
                            np.zeros(g.num_cells)))

        self.assertTrue(np.allclose(p, p_ex))
        self.assertTrue(np.allclose(P0u, P0u_ex))

        # Matrix computed with an already validated code
        M_known = (1.0 / 6.0 * np.matrix([
            [
                6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                8,
                0,
                0,
                0,
                0,
                0,
                -1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                2,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                6,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                -1,
                0,
                0,
                0,
                4,
                0,
                0,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                6,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                2,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                6,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                -1,
                0,
                0,
                2,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                -1,
                0,
                0,
                0,
                0,
                0,
                4,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                6,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                8,
                0,
                0,
                0,
                0,
                0,
                -1,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                2,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                6,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                0,
                4,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                6,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                4,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                6,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                2,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                6,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                1,
                0,
                0,
                2,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                -6,
                0,
                -6,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                -6,
                6,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                -6,
                0,
                -6,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                6,
                6,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                6,
                0,
                -6,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                -6,
                6,
                0,
                0,
                0,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                6,
                0,
                -6,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
            [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                6,
                6,
                0,
                0,
                -6,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
            ],
        ]))

        self.assertTrue(np.allclose(M.todense(), M_known))
Beispiel #27
0
    def test_rt0_2d_iso_simplex_mixed_bc(self):
        g = pp.simplex.StructuredTriangleGrid([2, 2], [1, 1])
        g.compute_geometry()

        kxx = np.ones(g.num_cells)
        perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kxx, kzz=1)

        tol = 1e-6
        bf = g.tags["domain_boundary_faces"].nonzero()[0]
        bf_centers = g.face_centers[:, bf]
        left = bf_centers[0, :] < 0 + tol
        right = bf_centers[0, :] > 1 - tol

        labels = np.array(["neu"] * bf.size)
        labels[left] = "rob"
        labels[right] = "dir"

        bc = pp.BoundaryCondition(g, bf, labels)
        bc.robin_weight[bf[left]] = 2

        bc_val = np.zeros(g.num_faces)
        bc_val[bf[left]] = 3

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

        param = pp.Parameters(g)
        param.set_tensor(solver, perm)
        param.set_bc(solver, bc)
        param.set_bc_val(solver, bc_val)

        data = {"param": param}
        M, rhs = solver.matrix_rhs(g, data)
        up = sps.linalg.spsolve(M, rhs)

        p = solver.extract_p(g, up)
        u = solver.extract_u(g, up)
        P0u = solver.project_u(g, u, data)

        p_ex = 1 - g.cell_centers[0, :]
        P0u_ex = np.vstack((np.ones(g.num_cells),
                            np.zeros(g.num_cells),
                            np.zeros(g.num_cells)))

        self.assertTrue(np.allclose(p, p_ex))
        self.assertTrue(np.allclose(P0u, P0u_ex))

        # Matrix computed with an already validated code
        M_known = 1./6. * np.matrix(
           [[ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 8, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [-1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,-6, 0, 0, 6, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 0, 0],
            [ 0, 0, 0,-1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 0, 0, 0, 0],
            [ 0,-1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0,-6, 0, 0, 6, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0,-6, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0],
            [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0,-6, 0, 0, 6, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0,-6, 0, 0, 6],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,-6, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0],
            [-6, 0,-6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0,-6, 6, 0, 0, 0, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0,-6, 0,-6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 6, 6, 0, 0, 0, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 6, 0,-6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 0, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0,-6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0]])

        self.assertTrue(np.allclose(M.todense(), M_known))