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))
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))
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))
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:]
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))
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))
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))
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)
def homo_mortar(g): return { "scheme": pp.RT0("flow"), "dof": { "cells": 1, "faces": 1 }, "label": "homo_mortar" }
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()
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)
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))
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))
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_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))
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
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))
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))
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))
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))
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))
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))