def test_p1_1d_ani(self): g = pp.structured.CartGrid(3, 1) g.compute_geometry() kxx = np.sin(g.cell_centers[0, :]) + 1 perm = pp.SecondOrderTensor(3, kxx, kyy=1, kzz=1) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["neu"]) solver = pp.P1(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( [ [3.4976884, -3.4976884, 0., 0.], [-3.4976884, 7.93596501, -4.43827662, 0.], [0., -4.43827662, 9.65880718, -5.22053056], [0., 0., -5.22053056, 5.22053056], ] ) self.assertTrue(np.allclose(M, M.T)) self.assertTrue(np.allclose(M, M_known))
def test_p1_2d_ani_simplex_surf(self): g = pp.simplex.StructuredTriangleGrid([1, 1], [1, 1]) g.compute_geometry() kxx = np.square(g.cell_centers[1, :]) + 1 kyy = np.square(g.cell_centers[0, :]) + 1 kxy = -np.multiply(g.cell_centers[0, :], g.cell_centers[1, :]) perm = pp.SecondOrderTensor(3, kxx=kxx, kyy=kyy, kxy=kxy, kzz=1) R = cg.rot(np.pi / 3., [1, 1, 0]) perm.rotate(R) g.nodes = np.dot(R, g.nodes) g.compute_geometry() bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["neu"]) solver = pp.P1(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( [ [1.11111111, -0.66666667, -0.66666667, 0.22222222], [-0.66666667, 1.5, 0., -0.83333333], [-0.66666667, 0., 1.5, -0.83333333], [0.22222222, -0.83333333, -0.83333333, 1.44444444], ] ) self.assertTrue(np.allclose(M, M.T)) self.assertTrue(np.allclose(M, M_known))
def test_p1_convergence_2d_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) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["dir"]) bc_val = np.zeros(g.num_nodes) bc_val[bn] = p_ex(g.nodes[:, bn]) solver = pp.P1(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}) p = sps.linalg.spsolve(M, rhs) err = np.sum(np.abs(p - p_ex(g.nodes))) self.assertTrue(np.isclose(err, 0))
def test_p1_1d(self): g = pp.structured.CartGrid(1, 1) g.compute_geometry() kxx = np.ones(g.num_cells) perm = pp.SecondOrderTensor(3, kxx, kyy=1, kzz=1) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["neu"]) solver = pp.P1(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([[1., -1.], [-1., 1.]]) self.assertTrue(np.allclose(M, M_known)) solver = pp.P1MassMatrix(physics="flow") M = solver.matrix(g, {"param": param}).todense() M_known = np.matrix([[2., 1.], [1., 2.]]) / 6. self.assertTrue(np.allclose(M, M_known))
def test_p1_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) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["neu"]) solver = pp.P1(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( [ [1., -0.5, -0.5, 0.], [-0.5, 1., 0., -0.5], [-0.5, 0., 1., -0.5], [0., -0.5, -0.5, 1.], ] ) self.assertTrue(np.allclose(M, M.T)) self.assertTrue(np.allclose(M, M_known)) solver = pp.P1MassMatrix(physics="flow") M = solver.matrix(g, {"param": param}).todense() M_known = ( np.matrix( [ [1., 0.25, 0.25, 0.5], [0.25, 0.5, 0., 0.25], [0.25, 0., 0.5, 0.25], [0.5, 0.25, 0.25, 1.], ] ) / 6. ) self.assertTrue(np.allclose(M, M_known))
def test_p1_convergence_1d_not_exact(self): p_ex = lambda pt: np.sin(2 * np.pi * pt[0, :]) source_ex = lambda pt: 4 * np.pi ** 2 * np.sin(2 * np.pi * pt[0, :]) known_errors = [ 0.0739720694066, 0.0285777089832, 0.00791150843359, 0.00202828006648, 0.00051026002257, 0.000127765008718, 3.19537621983e-05, ] for i, known_error in zip(np.arange(7), known_errors): g = pp.structured.CartGrid(4 * 2 ** i, 1) g.compute_geometry() kxx = np.ones(g.num_cells) perm = pp.SecondOrderTensor(3, kxx, kyy=1, kzz=1) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["dir"]) source_val = source_ex(g.nodes) solver = pp.P1(physics="flow") integral = pp.P1Source(physics="flow") param = pp.Parameters(g) param.set_tensor(solver, perm) param.set_bc(solver, bc) param.set_source(solver, source_val) M, _ = solver.matrix_rhs(g, {"param": param}) _, rhs = integral.matrix_rhs(g, {"param": param}) p = sps.linalg.spsolve(M, rhs) mass = pp.P1MassMatrix(physics="flow") M = mass.matrix(g, {"param": param}) error = np.sum(M.dot(np.abs(p - p_ex(g.nodes)))) self.assertTrue(np.isclose(error, known_error))
def test_p1_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) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, ["dir", "neu"]) solver = pp.P1(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( [ [1., 0., 0., 0.], [-3., 6., -3., 0.], [0., -3., 6., -3.], [0., 0., -3., 3.], ] ) self.assertTrue(np.allclose(M, M_known)) solver = pp.P1MassMatrix(physics="flow") M = solver.matrix(g, {"param": param}).todense() M_known = ( np.matrix( [[0., 0., 0., 0.], [1., 4., 1., 0.], [0., 1., 4., 1.], [0., 0., 1., 2.]] ) / 18. ) self.assertTrue(np.allclose(M, M_known))
def test_p1_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) bn = g.get_boundary_nodes() bc = pp.BoundaryConditionNode(g, bn, bn.size * ["neu"]) solver = pp.P1(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_p1_3d() self.assertTrue(np.allclose(M, M.T)) self.assertTrue(np.allclose(M, M_known)) solver = pp.P1MassMatrix(physics="flow") M = solver.matrix(g, {"param": param}).todense() M_known = ( np.matrix( [ [1., 0.5, 0.5, 0., 0.5, 0., 0., 0.], [0.5, 5., 1.5, 1., 1.5, 1., 2., 0.], [0.5, 1.5, 3., 0.5, 1., 0., 1., 0.], [0., 1., 0.5, 3., 0., 1., 1.5, 0.5], [0.5, 1.5, 1., 0., 3., 0.5, 1., 0.], [0., 1., 0., 1., 0.5, 3., 1.5, 0.5], [0., 2., 1., 1.5, 1., 1.5, 5., 0.5], [0., 0., 0., 0.5, 0., 0.5, 0.5, 1.], ] ) / 60. ) self.assertTrue(np.allclose(M, M_known))
def add_data(gb, domain, solver, case): if case == 1: kf = 1e4 else: kf = 1e-4 data = {"domain": domain, "aperture": 1e-4, "km": 1, "kf": kf} if_solver = solver == "vem" or solver == "rt0" or solver == "p1" if_p1 = solver == "p1" gb.add_node_props(["param", "is_tangential"]) for g, d in gb: param = Parameters(g) if g.dim == 3: kxx = np.ones(g.num_cells) * data["km"] perm = pp.SecondOrderTensor(3, kxx=kxx) else: kxx = np.ones(g.num_cells) * data["kf"] if if_solver: if g.dim == 2: perm = pp.SecondOrderTensor(g.dim, kxx=kxx, kyy=kxx, kzz=1) elif g.dim == 1: perm = pp.SecondOrderTensor(g.dim, kxx=kxx, kyy=1, kzz=1) else: # g.dim == 0 perm = pp.SecondOrderTensor(g.dim, kxx=kxx, kyy=1, kzz=1) else: perm = pp.SecondOrderTensor(3, kxx=kxx) param.set_tensor("flow", perm) aperture = np.power(data["aperture"], gb.dim_max() - g.dim) param.set_aperture(aperture * np.ones(g.num_cells)) param.set_source("flow", np.zeros(g.num_cells)) if if_p1: # for P1 a different handling of the boundary conditions bound_nodes = g.get_boundary_nodes() if bound_nodes.size == 0: bc = pp.BoundaryConditionNode(g, np.empty(0), np.empty(0)) bc_val = np.empty(0) else: p_press, b_in, b_out = b_pressure_node(g) labels = np.array(["neu"] * bound_nodes.size) labels[p_press] = "dir" bc_val = np.zeros(g.num_nodes) bc_val[bound_nodes[b_in]] = 1 bc_val[bound_nodes[b_out]] = -1 param.set_bc_val("flow", bc_val) bc = pp.BoundaryConditionNode(g, bound_nodes, labels) else: bound_faces = g.tags["domain_boundary_faces"].nonzero()[0] if bound_faces.size == 0: bc = BoundaryCondition(g, np.empty(0), np.empty(0)) param.set_bc("flow", bc) else: p_press, b_in, b_out = b_pressure(g) labels = np.array(["neu"] * bound_faces.size) labels[p_press] = "dir" bc_val = np.zeros(g.num_faces) bc_val[bound_faces[b_in]] = 1 bc_val[bound_faces[b_out]] = -1 param.set_bc_val("flow", bc_val) bc = BoundaryCondition(g, bound_faces, labels) param.set_bc("flow", bc) d["is_tangential"] = True d["param"] = param gb.add_edge_props("kn") for e, d in gb.edges(): g_l = gb.nodes_of_edge(e)[0] mg = d["mortar_grid"] check_P = mg.low_to_mortar_avg() kxx = data["kf"] gamma = np.power( check_P * gb.node_props(g_l, "param").get_aperture(), 1. / (gb.dim_max() - g_l.dim), ) d["kn"] = kxx * np.ones(mg.num_cells) / gamma
def add_data(gb, solver): data = {"km": 1, "kf_high": 1e2, "kf_low": 1e-2, "aperture": 1e-2} if_solver = solver == "vem" or solver == "rt0" or solver == "p1" if_p1 = solver == "p1" gb.add_node_props(["param", "is_tangential"]) for g, d in gb: param = pp.Parameters(g) if g.dim == 2: kxx = np.ones(g.num_cells) * data["km"] if if_solver: perm = pp.SecondOrderTensor(g.dim, kxx=kxx, kyy=kxx, kzz=1) else: perm = pp.SecondOrderTensor(3, kxx=kxx) elif g.dim == 1: if g.cell_centers[1, 0] > 0.25 and g.cell_centers[1, 0] < 0.55: kxx = np.ones(g.num_cells) * data["kf_low"] else: kxx = np.ones(g.num_cells) * data["kf_high"] if if_solver: perm = pp.SecondOrderTensor(g.dim, kxx=kxx, kyy=1, kzz=1) else: perm = pp.SecondOrderTensor(3, kxx=kxx) param.set_tensor("flow", perm) aperture = np.power(data["aperture"], gb.dim_max() - g.dim) param.set_aperture(aperture * np.ones(g.num_cells)) param.set_source("flow", np.zeros(g.num_cells)) if if_p1: # for P1 a different handling of the boundary conditions bound_nodes = g.get_boundary_nodes() if bound_nodes.size == 0: bc = pp.BoundaryConditionNode(g, np.empty(0), np.empty(0)) bc_val = np.empty(0) else: bound_node_coords = g.nodes[:, bound_nodes] top = bound_node_coords[1, :] > domain()["ymax"] - tol() bottom = bound_node_coords[1, :] < domain()["ymin"] + tol() labels = np.array(["neu"] * bound_nodes.size) labels[np.logical_or(top, bottom)] = "dir" bc_val = np.zeros(g.num_nodes) bc_val[bound_nodes[top]] = 1 param.set_bc_val("flow", bc_val) bc = pp.BoundaryConditionNode(g, bound_nodes, labels) else: bound_faces = g.get_boundary_faces() if bound_faces.size == 0: bc = pp.BoundaryCondition(g, np.empty(0), np.empty(0)) else: bound_face_centers = g.face_centers[:, bound_faces] top = bound_face_centers[1, :] > domain()["ymax"] - tol() bottom = bound_face_centers[1, :] < domain()["ymin"] + tol() labels = np.array(["neu"] * bound_faces.size) labels[np.logical_or(top, bottom)] = "dir" bc_val = np.zeros(g.num_faces) bc_val[bound_faces[top]] = 1 param.set_bc_val("flow", bc_val) bc = pp.BoundaryCondition(g, bound_faces, labels) param.set_bc("flow", bc) d["is_tangential"] = True d["param"] = param gb.add_edge_props("kn") for e, d in gb.edges(): g_l = gb.nodes_of_edge(e)[0] mg = d["mortar_grid"] check_P = mg.low_to_mortar_avg() if g_l.dim == 1: if g_l.cell_centers[1, 0] > 0.25 and g_l.cell_centers[1, 0] < 0.55: kxx = data["kf_low"] else: kxx = data["kf_high"] else: kxx = data["kf_high"] gamma = np.power( check_P * gb.node_props(g_l, "param").get_aperture(), 1.0 / (gb.dim_max() - g_l.dim), ) d["kn"] = kxx * np.ones(mg.num_cells) / gamma