def tet_grid(nx=None): if nx is None: nx = np.array([2, 2, 2]) g = pp.StructuredTetrahedralGrid(nx) g.compute_geometry() return g
def test_changing_bc_by_cells(self): """ Test that we can change the boundary condition by specifying the boundary cells """ g = pp.StructuredTetrahedralGrid([2, 2, 2], physdims=(1, 1, 1)) g.compute_geometry() bc = pp.BoundaryConditionVectorial(g) k = pp.FourthOrderTensor(g.dim, np.ones(g.num_cells), np.ones(g.num_cells)) stress_neu, bound_stress_neu = pp.numerics.fv.mpsa.mpsa( g, k, bc, inverter="python") faces = g.face_centers[2] < 1e-10 bc.is_rob[:, faces] = True bc.is_neu[bc.is_rob] = False stress_rob, bound_stress_rob = pp.numerics.fv.mpsa.mpsa( g, k, bc, inverter="python") # Update should not change anything cells = np.argwhere(g.cell_faces[faces, :])[:, 1].ravel() cells = np.unique(cells) stress, bound_stress = pp.numerics.fv.mpsa.mpsa_update_partial( stress_neu, bound_stress_neu, g, k, bc, cells=cells, inverter="python") self.assertTrue(np.allclose((stress - stress_rob).data, 0)) self.assertTrue(np.allclose((bound_stress - bound_stress_rob).data, 0))
def test_default_basis_3d(self): g = pp.StructuredTetrahedralGrid([1, 1, 1]) bc = pp.BoundaryConditionVectorial(g) basis_known = np.array([ [[1] * 18, [0] * 18, [0] * 18], [[0] * 18, [1] * 18, [0] * 18], [[0] * 18, [0] * 18, [1] * 18], ]) self.assertTrue(np.allclose(bc.basis, basis_known))
def test_tetrahedron_grid(self): g = pp.StructuredTetrahedralGrid([1, 1, 1]) g.compute_geometry() f = g.face_centers[2] < 1e-10 true_nodes = np.where(g.nodes[2] < 1e-10)[0] g.nodes[:2] = g.nodes[:2] + 0.2 * np.random.random(g.nodes.shape)[:2] g.nodes[2] = g.nodes[2] + 0.2 * np.random.rand(1) g.compute_geometry() h, sub_f, sub_n = pp.partition.extract_subgrid(g, f, faces=True) self.assertTrue(np.array_equal(true_nodes, sub_n)) self.assertTrue(np.array_equal(np.where(f)[0], sub_f)) self.compare_grid_geometries(g, h, None, f, true_nodes)
def test_mvem_3d(self): g = pp.StructuredTetrahedralGrid([1, 1, 1], [1, 1, 1]) g.compute_geometry() kxx = np.ones(g.num_cells) perm = pp.SecondOrderTensor(kxx=kxx, kyy=kxx, kzz=kxx) bf = g.get_boundary_faces() bc = pp.BoundaryCondition(g, bf, bf.size * ["dir"]) vect = np.vstack( (7 * g.cell_volumes, 4 * g.cell_volumes, 3 * g.cell_volumes) ).ravel(order="F") b = self._matrix(g, perm, bc, vect) b_known = np.array( [ -0.16666667, -0.16666667, 1.16666667, 0.08333333, 1.75, 2.0, 0.58333333, 1.5, 0.08333333, -1.5, -2.0, -0.08333333, -0.58333333, -1.75, -1.16666667, 0.16666667, -0.08333333, 0.16666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ] ) self.assertTrue(np.allclose(b, b_known))
def test_simplex_3d_sub_face(self): """ Test that we reconstruct the exact solution on subfaces """ nx = 2 ny = 2 nz = 2 g = pp.StructuredTetrahedralGrid([nx, ny, nz], physdims=[1, 1, 1]) g.compute_geometry() s_t = pp.fvutils.SubcellTopology(g) kxx = 10 * np.ones(g.num_cells) k = pp.SecondOrderTensor(kxx) bc = pp.BoundaryCondition(g) bc.is_dir[g.get_all_boundary_faces()] = True bc.is_neu[bc.is_dir] = False bc = pp.fvutils.boundary_to_sub_boundary(bc, s_t) p_b = np.sum(-g.face_centers, axis=0) p_b = p_b[s_t.fno_unique] mpfa = pp.Mpfa("flow") flux, bound_flux, p_t_cell, p_t_bound = mpfa.mpfa(g, k, bc, eta=0, inverter="python") div = pp.fvutils.scalar_divergence(g) hf2f = pp.fvutils.map_hf_2_f(nd=1, g=g) P = sps.linalg.spsolve(div * hf2f * flux, -div * hf2f * bound_flux * p_b) P_hf = p_t_cell * P + p_t_bound * p_b _, IA = np.unique(s_t.fno_unique, True) P_f = P_hf[IA] self.assertTrue( np.all(np.abs(P + np.sum(g.cell_centers, axis=0)) < 1e-10)) self.assertTrue( np.all(np.abs(P_f + np.sum(g.face_centers, axis=0)) < 1e-10))
def test_simplex_3d_dirichlet(self): """ Test that we retrieve a linear solution exactly """ nx = 2 ny = 2 nz = 2 g = pp.StructuredTetrahedralGrid([nx, ny, nz], physdims=[1, 1, 1]) g.compute_geometry() np.random.seed(2) lam = np.ones(g.num_cells) mu = np.ones(g.num_cells) k = pp.FourthOrderTensor(mu, lam) s_t = pp.fvutils.SubcellTopology(g) bc = pp.BoundaryConditionVectorial(g) bc.is_dir[:, g.get_all_boundary_faces()] = True bc.is_neu[bc.is_dir] = False x0 = np.array([[1, 2, 3]]).T u_b = g.face_centers + x0 stress, bound_stress, grad_cell, grad_bound = pp.numerics.fv.mpsa.mpsa( g, k, bc, eta=0, hf_disp=True, inverter="python") div = pp.fvutils.vector_divergence(g) U = sps.linalg.spsolve(div * stress, -div * bound_stress * u_b.ravel("F")) U_hf = (grad_cell * U + grad_bound * u_b.ravel("F")).reshape( (g.dim, -1), order="F") _, IA = np.unique(s_t.fno_unique, True) U_f = U_hf[:, IA] U = U.reshape((g.dim, -1), order="F") self.assertTrue(np.all(np.abs(U - g.cell_centers - x0) < 1e-10)) self.assertTrue(np.all(np.abs(U_f - g.face_centers - x0) < 1e-10))
def test_simplex_3d_dirichlet(self): """ Test that we retrieve a linear solution exactly """ nx = 2 ny = 2 nz = 2 g = pp.StructuredTetrahedralGrid([nx, ny, nz], physdims=[1, 1, 1]) g.compute_geometry() np.random.seed(2) kxx = np.ones(g.num_cells) k = pp.SecondOrderTensor(kxx) s_t = pp.fvutils.SubcellTopology(g) bc = pp.BoundaryCondition(g) bc.is_dir[g.get_all_boundary_faces()] = True bc.is_neu[bc.is_dir] = False p0 = 1 p_b = np.sum(g.face_centers, axis=0) + p0 mpfa = pp.Mpfa("flow") flux, bound_flux, p_t_cell, p_t_bound = mpfa.mpfa(g, k, bc, eta=0, inverter="python") div = pp.fvutils.scalar_divergence(g) P = sps.linalg.spsolve(div * flux, -div * bound_flux * p_b) P_f = p_t_cell * P + p_t_bound * p_b self.assertTrue( np.all(np.abs(P - np.sum(g.cell_centers, axis=0) - p0) < 1e-10)) self.assertTrue( np.all(np.abs(P_f - np.sum(g.face_centers, axis=0) - p0) < 1e-10))
def test_simplex_3d_boundary(self): """ Even if we do not get exact solution at interiour we should be able to retrieve the boundary conditions """ nx = 2 ny = 2 nz = 2 g = pp.StructuredTetrahedralGrid([nx, ny, nz], physdims=[1, 1, 1]) g.compute_geometry() np.random.seed(2) lam = 10 * np.random.rand(g.num_cells) mu = 10 * np.random.rand(g.num_cells) k = pp.FourthOrderTensor(mu, lam) s_t = pp.fvutils.SubcellTopology(g) bc = pp.BoundaryConditionVectorial(g) dir_ind = g.get_all_boundary_faces()[[0, 2, 5, 8, 10, 13, 15, 21]] bc.is_dir[:, dir_ind] = True bc.is_neu[bc.is_dir] = False u_b = np.random.randn(g.face_centers.shape[0], g.face_centers.shape[1]) stress, bound_stress, grad_cell, grad_bound = pp.numerics.fv.mpsa.mpsa( g, k, bc, eta=0, hf_disp=True, inverter="python") div = pp.fvutils.vector_divergence(g) U = sps.linalg.spsolve(div * stress, -div * bound_stress * u_b.ravel("F")) U_hf = (grad_cell * U + grad_bound * u_b.ravel("F")).reshape( (g.dim, -1), order="F") _, IA = np.unique(s_t.fno_unique, True) U_f = U_hf[:, IA] self.assertTrue( np.all(np.abs(U_f[:, dir_ind] - u_b[:, dir_ind]) < 1e-10))
def test_simplex_3d_boundary(self): """ Even if we do not get exact solution at interiour we should be able to retrieve the boundary conditions """ nx = 2 ny = 2 nz = 2 g = pp.StructuredTetrahedralGrid([nx, ny, nz], physdims=[1, 1, 1]) g.compute_geometry() np.random.seed(2) kxx = 10 * np.random.rand(g.num_cells) k = pp.SecondOrderTensor(kxx) bc = pp.BoundaryCondition(g) dir_ind = g.get_all_boundary_faces()[[0, 2, 5, 8, 10, 13, 15, 21]] bc.is_dir[dir_ind] = True bc.is_neu[bc.is_dir] = False p_b = np.random.randn(g.face_centers.shape[1]) mpfa = pp.Mpfa("flow") flux, bound_flux, p_t_cell, p_t_bound = mpfa.mpfa(g, k, bc, eta=0, inverter="python") div = pp.fvutils.scalar_divergence(g) P = sps.linalg.spsolve(div * flux, -div * bound_flux * p_b.ravel("F")) P_f = p_t_cell * P + p_t_bound * p_b self.assertTrue(np.all(np.abs(P_f[dir_ind] - p_b[dir_ind]) < 1e-10))
def test_tag_3d_simplex(self): g = pp.StructuredTetrahedralGrid([2] * 3, [1] * 3) self.assertTrue( np.array_equal(g.tags["fracture_faces"], [False] * g.num_faces)) self.assertTrue( np.array_equal(g.tags["fracture_nodes"], [False] * g.num_nodes)) self.assertTrue( np.array_equal(g.tags["tip_faces"], [False] * g.num_faces)) self.assertTrue( np.array_equal(g.tags["tip_nodes"], [False] * g.num_nodes)) known = np.array( [ True, True, True, True, True, True, False, False, False, False, True, False, False, True, False, False, True, False, True, False, False, True, False, True, True, True, False, True, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, True, False, False, False, True, True, True, False, False, True, False, True, True, False, True, True, False, True, False, False, False, False, False, True, False, False, False, False, False, True, False, True, False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, True, True, True, False, False, True, False, True, True, True, True, True, True, True, True, True, True, ], dtype=bool, ) self.assertTrue(np.array_equal(g.tags["domain_boundary_faces"], known)) known = np.array( [ True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, ], dtype=bool, ) self.assertTrue(np.array_equal(g.tags["domain_boundary_nodes"], known))
self.assertTrue(mg.num_sides() == 1) self.assertTrue(np.all(mg.primary_to_mortar_avg().A == [0, 1, 0])) self.assertTrue(np.all(mg.primary_to_mortar_int().A == [0, 1, 0])) self.assertTrue(np.all(mg.secondary_to_mortar_avg().A == [0, 1])) self.assertTrue(np.all(mg.secondary_to_mortar_int().A == [0, 1])) @pytest.mark.parametrize( "g", [ pp.PointGrid([0, 0, 0]), pp.CartGrid([2]), pp.CartGrid([2, 2]), pp.CartGrid([2, 2, 2]), pp.StructuredTriangleGrid([2, 2]), pp.StructuredTetrahedralGrid([1, 1, 1]), ], ) def test_pickle_grid(g): """Test that grids can be pickled. Write, read and compare.""" fn = "tmp.grid" pickle.dump(g, open(fn, "wb")) g_read = pickle.load(open(fn, "rb")) test_utils.compare_grids(g, g_read) test_utils.delete_file(fn) @pytest.mark.parametrize("g",[ pp.PointGrid([0, 0, 0]), pp.CartGrid([2]),