def test_domain_cut_in_two(self): """ test domain cut in two. We place 1 dirichlet on top. zero dirichlet on bottom and 0 neumann on sides. Further we place 1 displacement on fracture. this should give us displacement 1 on top cells and 0 on bottom cells and zero traction on all faces """ frac = np.array([[0,0,1], [0,3,1], [3,3,1], [3,0,1]]).T g = meshing.cart_grid([frac], [3,3,2]).grids_of_dimension(3)[0] data = {'param': Parameters(g)} tol = 1e-6 frac_bnd = g.has_face_tag(FaceTag.FRACTURE) top = g.face_centers[2] > 2 - tol bot = g.face_centers[2] < tol dir_bound = top | bot | frac_bnd bound = bc.BoundaryCondition(g, dir_bound, 'dir') bc_val = np.zeros((g.dim, g.num_faces)) bc_val[:, top] = np.ones((g.dim, np.sum(top))) frac_slip = np.zeros((g.dim, g.num_faces)) frac_slip[:, frac_bnd] = np.ones(np.sum(frac_bnd)) data['param'].set_bc('mechanics', bound) data['param'].set_bc_val('mechanics', bc_val.ravel('F')) data['param'].set_slip_distance(frac_slip.ravel('F')) solver = mpsa.FracturedMpsa() A, b = solver.matrix_rhs(g, data) u = np.linalg.solve(A.A, b) u_f = solver.extract_frac_u(g, u) u_c = solver.extract_u(g, u) u_c = u_c.reshape((3, -1), order='F') T = solver.traction(g, data, u) top_cells = g.cell_centers[2] > 1 mid_ind = int(round(u_f.size/2)) u_left = u_f[:mid_ind] u_right = u_f[mid_ind:] assert np.allclose(u_left, 1) assert np.allclose(u_right, 0) assert np.allclose(u_c[:, top_cells], 1) assert np.allclose(u_c[:, ~top_cells], 0) assert np.allclose(T, 0)
def test_uniform_strain(self): g_list = setup_grids.setup_2d() for g in g_list: bound_faces = np.argwhere( np.abs(g.cell_faces).sum(axis=1).A.ravel("F") == 1 ) bound = bc.BoundaryCondition( g, bound_faces.ravel("F"), ["dir"] * bound_faces.size ) mu = 1 l = 1 constit = setup_stiffness(g, mu, l) # Python inverter is most efficient for small problems stress, bound_stress = mpsa.mpsa(g, constit, bound, inverter="python") div = fvutils.vector_divergence(g) a = div * stress xc = g.cell_centers xf = g.face_centers gx = np.random.rand(1) gy = np.random.rand(1) dc_x = np.sum(xc * gx, axis=0) dc_y = np.sum(xc * gy, axis=0) df_x = np.sum(xf * gx, axis=0) df_y = np.sum(xf * gy, axis=0) d_bound = np.zeros((g.dim, g.num_faces)) d_bound[0, bound.is_dir] = df_x[bound.is_dir] d_bound[1, bound.is_dir] = df_y[bound.is_dir] rhs = div * bound_stress * d_bound.ravel("F") d = np.linalg.solve(a.todense(), -rhs) traction = stress * d + bound_stress * d_bound.ravel("F") s_xx = (2 * mu + l) * gx + l * gy s_xy = mu * (gx + gy) s_yx = mu * (gx + gy) s_yy = (2 * mu + l) * gy + l * gx n = g.face_normals traction_ex_x = s_xx * n[0] + s_xy * n[1] traction_ex_y = s_yx * n[0] + s_yy * n[1] self.assertTrue(np.max(np.abs(d[::2] - dc_x)) < 1e-8) self.assertTrue(np.max(np.abs(d[1::2] - dc_y)) < 1e-8) self.assertTrue(np.max(np.abs(traction[::2] - traction_ex_x)) < 1e-8) self.assertTrue(np.max(np.abs(traction[1::2] - traction_ex_y)) < 1e-8)
def test_elliptic_data_given_values(self): """ test that the elliptic data initialize the correct data. """ p = np.random.rand(3, 10) g = simplex.TetrahedralGrid(p) # Set values bc_val = np.pi * np.ones(g.num_faces) dir_faces = g.tags["domain_boundary_faces"].nonzero()[0] bc_cond = bc.BoundaryCondition(g, dir_faces, ["dir"] * dir_faces.size) porosity = 1 / np.pi * np.ones(g.num_cells) apperture = 0.5 * np.ones(g.num_cells) kxx = 2 * np.ones(g.num_cells) kyy = 3 * np.ones(g.num_cells) K = tensor.SecondOrderTensor(g.dim, kxx, kyy) source = 42 * np.ones(g.num_cells) # Assign to parameter param = Parameters(g) param.set_bc_val("flow", bc_val) param.set_bc("flow", bc_cond) param.set_porosity(porosity) param.set_aperture(apperture) param.set_tensor("flow", K) param.set_source("flow", source) # Define EllipticData class class Data(EllipticDataAssigner): def __init__(self, g, data): EllipticDataAssigner.__init__(self, g, data) def bc(self): return bc_cond def bc_val(self): return bc_val def porosity(self): return porosity def aperture(self): return apperture def permeability(self): return K def source(self): return source elliptic_data = dict() Data(g, elliptic_data) elliptic_param = elliptic_data["param"] self.check_parameters(elliptic_param, param)
def bc_labels(g): bound_faces = g.tags["domain_boundary_faces"].nonzero()[0] bound_face_centers = g.face_centers[:, bound_faces] left = bound_face_centers[0] < 1e-6 right = bound_face_centers[0] > 10 - 1e-6 labels = np.array(["neu"] * bound_faces.size) labels[np.logical_or(right, left)] = "dir" bc_labels = bc.BoundaryCondition(g, bound_faces, labels) return bc_labels
def bc_labels(g): bound_faces = g.get_boundary_faces() bound_face_centers = g.face_centers[:, bound_faces] left = bound_face_centers[0] < 1e-6 right = bound_face_centers[0] > 10 - 1e-6 labels = np.array(['neu'] * bound_faces.size) labels[np.logical_or(right, left)] = 'dir' bc_labels = bc.BoundaryCondition(g, bound_faces, labels) return bc_labels
def setup_3d(nx, simplex_grid=False): f1 = np.array([[0.2, 0.2, 0.8, 0.8], [0.2, 0.8, 0.8, 0.2], [0.5, 0.5, 0.5, 0.5]]) f2 = np.array([[0.2, 0.8, 0.8, 0.2], [0.5, 0.5, 0.5, 0.5], [0.2, 0.2, 0.8, 0.8]]) f3 = np.array([[0.5, 0.5, 0.5, 0.5], [0.2, 0.8, 0.8, 0.2], [0.2, 0.2, 0.8, 0.8]]) fracs = [f1, f2, f3] if not simplex_grid: gb = meshing.cart_grid(fracs, nx, physdims=[1, 1, 1]) else: mesh_kwargs = {} mesh_size = .3 mesh_kwargs = { "mesh_size_frac": mesh_size, "mesh_size_bound": 2 * mesh_size, "mesh_size_min": mesh_size / 20, } domain = {"xmin": 0, "ymin": 0, "xmax": 1, "ymax": 1} gb = meshing.simplex_grid(fracs, domain, **mesh_kwargs) gb.add_node_props(["param"]) for g, d in gb: a = 0.01 / np.max(nx) a = np.power(a, gb.dim_max() - g.dim) param = Parameters(g) param.set_aperture(a) # BoundaryCondition left = g.face_centers[0] < 1e-6 top = g.face_centers[2] > 1 - 1e-6 dir_faces = np.argwhere(left) bc_cond = bc.BoundaryCondition(g, dir_faces, ["dir"] * dir_faces.size) bc_val = np.zeros(g.num_faces) bc_val[dir_faces] = 3 bc_val[top] = 2.4 param.set_bc("flow", bc_cond) param.set_bc_val("flow", bc_val) # Source and sink src = np.zeros(g.num_cells) src[0] = np.pi src[-1] = -np.pi param.set_source("flow", src) d["param"] = param gb.add_edge_props("kn") for e, d in gb.edges(): g = gb.nodes_of_edge(e)[0] mg = d["mortar_grid"] check_P = mg.low_to_mortar_avg() d["kn"] = 1 / (check_P * gb.node_props(g, "param").get_aperture()) return gb
def darcy_dualVEM_example3(**kwargs): ####################### # Simple 3d Darcy problem with known exact solution ####################### Nx = Ny = Nz = 7 g = structured.CartGrid([Nx, Ny, Nz], [1, 1, 1]) g.compute_geometry() kxx = np.ones(g.num_cells) perm = tensor.SecondOrderTensor(g.dim, kxx) def funP_ex(pt): return (np.sin(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]) * np.sin(2 * np.pi * pt[2])) def funU_ex(pt): return [ -2 * np.pi * np.cos(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]) * np.sin(2 * np.pi * pt[2]), -2 * np.pi * np.sin(2 * np.pi * pt[0]) * np.cos(2 * np.pi * pt[1]) * np.sin(2 * np.pi * pt[2]), -2 * np.pi * np.sin(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]) * np.cos(2 * np.pi * pt[2]), ] def fun(pt): return 12 * np.pi**2 * funP_ex(pt) f = np.array([fun(pt) for pt in g.cell_centers.T]) b_faces = g.get_all_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size) bnd_val = np.zeros(g.num_faces) bnd_val[b_faces] = funP_ex(g.face_centers[:, b_faces]) solver = dual.DualVEM() data = {"perm": perm, "source": f, "bc": bnd, "bc_val": bnd_val} D, rhs = solver.matrix_rhs(g, data) up = sps.linalg.spsolve(D, rhs) u, p = solver.extract_u(g, up), solver.extract_p(g, up) P0u = solver.project_u(g, u) if kwargs["visualize"]: plot_grid(g, p, P0u) p_ex = error.interpolate(g, funP_ex) u_ex = error.interpolate(g, funU_ex) errors = np.array( [error.error_L2(g, p, p_ex), error.error_L2(g, P0u, u_ex)]) errors_known = np.array([0.1010936831876412, 0.0680593765009036]) assert np.allclose(errors, errors_known)
def darcy_dual_hybridVEM_example3(**kwargs): ####################### # Simple 3d Darcy problem with known exact solution ####################### Nx = Ny = Nz = 7 g = structured.CartGrid([Nx, Ny, Nz], [1, 1, 1]) g.compute_geometry() kxx = np.ones(g.num_cells) perm = tensor.SecondOrderTensor(g.dim, kxx) def funP_ex(pt): return np.sin(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1])\ * np.sin(2 * np.pi * pt[2]) def funU_ex(pt): return [-2 * np.pi * np.cos(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]) * np.sin(2 * np.pi * pt[2]), -2 * np.pi * np.sin(2 * np.pi * pt[0]) * np.cos(2 * np.pi * pt[1]) * np.sin(2 * np.pi * pt[2]), -2 * np.pi * np.sin(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]) * np.cos(2 * np.pi * pt[2])] def fun(pt): return 12 * np.pi**2 * funP_ex(pt) f = np.array([fun(pt) for pt in g.cell_centers.T]) b_faces = g.get_all_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ['dir'] * b_faces.size) bnd_val = np.zeros(g.num_faces) bnd_val[b_faces] = funP_ex(g.face_centers[:, b_faces]) solver = hybrid.HybridDualVEM() data = {'perm': perm, 'source': f, 'bc': bnd, 'bc_val': bnd_val} H, rhs = solver.matrix_rhs(g, data) l = sps.linalg.spsolve(H, rhs) u, p = solver.compute_up(g, l, data) P0u = dual.DualVEM().project_u(g, u) if kwargs['visualize']: plot_grid(g, p, P0u) p_ex = error.interpolate(g, funP_ex) u_ex = error.interpolate(g, funU_ex) np.set_printoptions(linewidth=999999) np.set_printoptions(precision=16) errors = np.array([error.error_L2(g, p, p_ex), error.error_L2(g, P0u, u_ex)]) errors_known = np.array([0.1010936831876412, 0.0680593765009036]) assert np.allclose(errors, errors_known)
def setup_3d(nx, simplex_grid=False): f1 = np.array([[0.2, 0.2, 0.8, 0.8], [0.2, 0.8, 0.8, 0.2], [0.5, 0.5, 0.5, 0.5]]) f2 = np.array([[0.2, 0.8, 0.8, 0.2], [0.5, 0.5, 0.5, 0.5], [0.2, 0.2, 0.8, 0.8]]) f3 = np.array([[0.5, 0.5, 0.5, 0.5], [0.2, 0.8, 0.8, 0.2], [0.2, 0.2, 0.8, 0.8]]) fracs = [f1, f2, f3] if not simplex_grid: gb = meshing.cart_grid(fracs, nx, physdims=[1, 1, 1]) else: mesh_kwargs = {} mesh_size = .3 mesh_kwargs = { 'mesh_size_frac': mesh_size, 'mesh_size_bound': 2 * mesh_size, 'mesh_size_min': mesh_size / 20 } domain = {'xmin': 0, 'ymin': 0, 'xmax': 1, 'ymax': 1} gb = meshing.simplex_grid(fracs, domain, **mesh_kwargs) gb.add_node_props(['param']) for g, d in gb: a = 0.01 / np.max(nx) a = np.power(a, gb.dim_max() - g.dim) param = Parameters(g) param.set_aperture(a) # BoundaryCondition left = g.face_centers[0] < 1e-6 top = g.face_centers[2] > 1 - 1e-6 dir_faces = np.argwhere(left) bc_cond = bc.BoundaryCondition(g, dir_faces, ['dir'] * dir_faces.size) bc_val = np.zeros(g.num_faces) bc_val[dir_faces] = 3 bc_val[top] = 2.4 param.set_bc('flow', bc_cond) param.set_bc_val('flow', bc_val) # Source and sink src = np.zeros(g.num_cells) src[0] = np.pi src[-1] = -np.pi param.set_source('flow', src) d['param'] = param gb.add_edge_props('kn') for e, d in gb.edges(): g = gb.nodes_of_edge(e)[0] d['kn'] = 1 / gb.node_props(g, 'param').get_aperture() return gb
def darcy_dual_hybridVEM_example1(**kwargs): ####################### # Simple 2d Darcy problem with known exact solution ####################### Nx = Ny = 25 g = structured.CartGrid([Nx, Ny], [1, 1]) g.compute_geometry() kxx = np.ones(g.num_cells) perm = tensor.SecondOrderTensor(g.dim, kxx) def funP_ex(pt): return np.sin(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]) def funU_ex(pt): return [ -2 * np.pi * np.cos(2 * np.pi * pt[0]) * np.sin(2 * np.pi * pt[1]), -2 * np.pi * np.sin(2 * np.pi * pt[0]) * np.cos(2 * np.pi * pt[1]), 0, ] def fun(pt): return 8 * np.pi**2 * funP_ex(pt) f = np.array([fun(pt) for pt in g.cell_centers.T]) b_faces = g.get_all_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size) bnd_val = np.zeros(g.num_faces) bnd_val[b_faces] = funP_ex(g.face_centers[:, b_faces]) solver = hybrid.HybridDualVEM() data = {"perm": perm, "source": f, "bc": bnd, "bc_val": bnd_val} H, rhs = solver.matrix_rhs(g, data) l = sps.linalg.spsolve(H, rhs) u, p = solver.compute_up(g, l, data) P0u = dual.DualVEM().project_u(g, u) if kwargs["visualize"]: plot_grid(g, p, P0u) p_ex = error.interpolate(g, funP_ex) u_ex = error.interpolate(g, funU_ex) errors = np.array( [error.error_L2(g, p, p_ex), error.error_L2(g, P0u, u_ex)]) errors_known = np.array([0.0210718223032, 0.00526933885613]) assert np.allclose(errors, errors_known)
def darcy_dualVEM_example2(**kwargs): ####################### # Simple 2d Darcy problem on a surface with known exact solution ####################### Nx = Ny = 25 g = simplex.StructuredTriangleGrid([Nx, Ny], [1, 1]) R = cg.rot(np.pi / 6., [0, 1, 1]) g.nodes = np.dot(R, g.nodes) g.compute_geometry() T = cg.tangent_matrix(g.nodes) kxx = np.ones(g.num_cells) perm = tensor.SecondOrderTensor(g.dim, kxx) def funP_ex(pt): return np.pi * pt[0] - 6 * pt[1] + np.exp(1) * pt[2] - 4 def funU_ex(pt): return np.dot(T, [-np.pi, 6, -np.exp(1)]) def fun(pt): return 0 f = np.array([fun(pt) for pt in g.cell_centers.T]) b_faces = g.get_all_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size) bnd_val = np.zeros(g.num_faces) bnd_val[b_faces] = funP_ex(g.face_centers[:, b_faces]) solver = dual.DualVEM() data = {"perm": perm, "source": f, "bc": bnd, "bc_val": bnd_val} D, rhs = solver.matrix_rhs(g, data) up = sps.linalg.spsolve(D, rhs) u, p = solver.extract_u(g, up), solver.extract_p(g, up) P0u = solver.project_u(g, u) if kwargs["visualize"]: plot_grid(g, p, P0u) p_ex = error.interpolate(g, funP_ex) u_ex = error.interpolate(g, funU_ex) errors = np.array( [error.error_L2(g, p, p_ex), error.error_L2(g, P0u, u_ex)]) errors_known = np.array([0, 0]) assert np.allclose(errors, errors_known)
def test_uniform_flow_cart_2d(): nx = np.array([13, 13]) g = structured.CartGrid(nx) g.compute_geometry() kxx = np.ones(g.num_cells) perm = tensor.SecondOrder(g.dim, kxx) bound_faces = np.argwhere( np.abs(g.cell_faces).sum(axis=1).A.ravel('F') == 1) bound = bc.BoundaryCondition(g, bound_faces, ['dir'] * bound_faces.size) discr = tpfa.Tpfa() d = _assign_params(g, perm, bound) discr.discretize(g, d) flux, bound_flux = d['flux'], d['bound_flux']
def test_unit_slip(self): """ Unit slip of fractures """ f = np.array([[0, 0, 1], [0, 2, 1], [2, 2, 1], [2, 0, 1]]).T g = meshing.cart_grid([f], [2, 2, 2]).grids_of_dimension(3)[0] data = {"param": Parameters(g)} bound = bc.BoundaryCondition(g, g.get_all_boundary_faces(), "dir") data["param"].set_bc("mechanics", bound) slip = np.ones(g.dim * g.num_faces) data["param"].set_slip_distance(slip) solver = StaticModel(g, data) solver.solve() solver.frac_displacement("d_f") solver.displacement("d_c") solver.save(["d_c"]) # test cell displacent around fractures d_c = data["d_c"] d_c = d_c.reshape((3, -1), order="F") frac_faces = g.frac_pairs frac_left = frac_faces[0] frac_right = frac_faces[1] cell_left = np.ravel(np.argwhere(g.cell_faces[frac_left, :])[:, 1]) cell_right = np.ravel(np.argwhere(g.cell_faces[frac_right, :])[:, 1]) # Test traction solver.traction("T") T_left = data["T"][:, frac_left] T_right = data["T"][:, frac_right] self.assertTrue(np.allclose(T_left, T_right)) # we have u_lhs - u_rhs = 1 so u_lhs should be positive self.assertTrue(np.all(d_c[:, cell_left] > 0)) self.assertTrue(np.all(d_c[:, cell_right] < 0)) # Test fracture displacement u_left = data["d_f"][:, :int(round(data["d_f"].shape[1] / 2))] u_right = data["d_f"][:, int(round(data["d_f"].shape[1] / 2)):] self.assertTrue(np.all(np.abs(u_left - u_right - 1) < 1e-10))
def test_zero_force(self): """ if nothing is touched nothing should happen """ f = np.array([[0, 0, 1], [0, 1, 1], [1, 1, 1], [1, 0, 1]]).T g = meshing.cart_grid([f], [4, 4, 2]).grids_of_dimension(3)[0] data = {'param': Parameters(g)} bound = bc.BoundaryCondition(g, g.get_all_boundary_faces(), 'dir') data['param'].set_bc('mechanics', bound) solver = StaticModel(g, data) d = solver.solve() solver.traction('T') assert np.all(d == 0) assert np.all(data['T'] == 0)
def test_zero_force(self): """ if nothing is touched nothing should happen """ f = np.array([[0, 0, 1], [0, 1, 1], [1, 1, 1], [1, 0, 1]]).T g = meshing.cart_grid([f], [4, 4, 2]).grids_of_dimension(3)[0] data = {"param": Parameters(g)} bound = bc.BoundaryCondition(g, g.get_all_boundary_faces(), "dir") data["param"].set_bc("mechanics", bound) solver = StaticModel(g, data) d = solver.solve() solver.traction("T") self.assertTrue(np.all(d == 0)) self.assertTrue(np.all(data["T"] == 0))
def test_one_cell_a_time_node_keyword(self): # Update one and one cell, and verify that the result is the same as # with a single computation. # The test is similar to what will happen with a memory-constrained # splitting. g = CartGrid([3, 3]) g.compute_geometry() # Assign random permeabilities, for good measure np.random.seed(42) kxx = np.random.random(g.num_cells) kyy = np.random.random(g.num_cells) # Ensure positive definiteness kxy = np.random.random(g.num_cells) * kxx * kyy perm = PermTensor(2, kxx=kxx, kyy=kyy, kxy=kxy) flux = sps.csr_matrix((g.num_faces, g.num_cells)) bound_flux = sps.csr_matrix((g.num_faces, g.num_faces)) faces_covered = np.zeros(g.num_faces, np.bool) bnd = bc.BoundaryCondition(g) cn = g.cell_nodes() for ci in range(g.num_cells): ind = np.zeros(g.num_cells) ind[ci] = 1 nodes = np.squeeze(np.where(cn * ind > 0)) partial_flux, partial_bound, _, _, active_faces = mpfa.mpfa_partial( g, perm, bnd, nodes=nodes, inverter="python") if np.any(faces_covered): partial_flux[faces_covered, :] *= 0 partial_bound[faces_covered, :] *= 0 faces_covered[active_faces] = True flux += partial_flux bound_flux += partial_bound flux_full, bound_flux_full, _, _ = mpfa.mpfa(g, perm, bnd, inverter="python") self.assertTrue((flux_full - flux).max() < 1e-8) self.assertTrue((flux_full - flux).min() > -1e-8) self.assertTrue((bound_flux - bound_flux_full).max() < 1e-8) self.assertTrue((bound_flux - bound_flux_full).min() > -1e-8)
def setup_2d_1d(nx, simplex_grid=False): frac1 = np.array([[0.2, 0.8], [0.5, 0.5]]) frac2 = np.array([[0.5, 0.5], [0.8, 0.2]]) fracs = [frac1, frac2] if not simplex_grid: gb = meshing.cart_grid(fracs, nx, physdims=[1, 1]) else: mesh_kwargs = {} mesh_size = .3 mesh_kwargs['mesh_size'] = { 'mode': 'constant', 'value': mesh_size, 'bound_value': 1 * mesh_size } domain = {'xmin': 0, 'ymin': 0, 'xmax': 1, 'ymax': 1} gb = meshing.simplex_grid(fracs, domain, **mesh_kwargs) gb.compute_geometry() gb.assign_node_ordering() internal_flag = FaceTag.FRACTURE [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb] gb.add_node_props(['param']) for g, d in gb: kxx = np.ones(g.num_cells) perm = tensor.SecondOrder(3, kxx) a = 0.01 / np.max(nx) a = np.power(a, gb.dim_max() - g.dim) param = Parameters(g) param.set_tensor('flow', perm) param.set_aperture(a) if g.dim == 2: bound_faces = g.get_boundary_faces() bound = bc.BoundaryCondition(g, bound_faces.ravel('F'), ['dir'] * bound_faces.size) bc_val = g.face_centers[1] param.set_bc('flow', bound) param.set_bc_val('flow', bc_val) d['param'] = param gb.add_edge_prop('kn') for e, d in gb.edges_props(): g = gb.sorted_nodes_of_edge(e)[0] d['kn'] = 1 / gb.node_prop(g, 'param').get_aperture() return gb
def test_one_cell_a_time_node_keyword(self): # Update one and one cell, and verify that the result is the same as # with a single computation. The test is similar to what will happen # with a memory-constrained splitting. g = CartGrid([3, 3]) g.compute_geometry() # Assign random permeabilities, for good measure np.random.seed(42) mu = np.random.random(g.num_cells) lmbda = np.random.random(g.num_cells) stiffness = StiffnessTensor(2, mu=mu, lmbda=lmbda) stress = sps.csr_matrix((g.num_faces * g.dim, g.num_cells * g.dim)) bound_stress = sps.csr_matrix( (g.num_faces * g.dim, g.num_faces * g.dim)) faces_covered = np.zeros(g.num_faces, np.bool) bnd = bc.BoundaryCondition(g) stress_full, bound_stress_full = mpsa.mpsa(g, stiffness, bnd, inverter='python') cn = g.cell_nodes() for ci in range(g.num_cells): ind = np.zeros(g.num_cells) ind[ci] = 1 nodes = np.squeeze(np.where(cn * ind > 0)) partial_stress, partial_bound, active_faces = \ mpsa.mpsa_partial(g, stiffness, bnd, nodes=nodes, inverter='python') if np.any(faces_covered): del_faces = self.expand_indices_nd( np.where(faces_covered)[0], g.dim) partial_stress[del_faces, :] *= 0 partial_bound[del_faces, :] *= 0 faces_covered[active_faces] = True stress += partial_stress bound_stress += partial_bound assert (stress_full - stress).max() < 1e-8 assert (stress_full - stress).min() > -1e-8 assert (bound_stress - bound_stress_full).max() < 1e-8 assert (bound_stress - bound_stress_full).min() > -1e-8
def test_conservation_of_momentum(self): pts = np.random.rand(3, 9) corners = [ [0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 1, 1, 0, 0, 1, 1], [0, 1, 0, 1, 0, 1, 0, 1], ] pts = np.hstack((corners, pts)) gt = simplex.TetrahedralGrid(pts) gc = structured.CartGrid([3, 3, 3], physdims=[1, 1, 1]) g_list = [gt, gc] [g.compute_geometry() for g in g_list] for g in g_list: g.compute_geometry() bot = np.ravel(np.argwhere(g.face_centers[1, :] < 1e-10)) left = np.ravel(np.argwhere(g.face_centers[0, :] < 1e-10)) dir_faces = np.hstack((left, bot)) bound = bc.BoundaryCondition( g, dir_faces.ravel("F"), ["dir"] * dir_faces.size ) constit = setup_stiffness(g) # Python inverter is most efficient for small problems stress, bound_stress = mpsa.mpsa(g, constit, bound, inverter="python") div = fvutils.vector_divergence(g) a = div * stress bndr = g.get_all_boundary_faces() d_x = np.random.rand(bndr.size) d_y = np.random.rand(bndr.size) d_bound = np.zeros((g.dim, g.num_faces)) d_bound[0, bndr] = d_x d_bound[1, bndr] = d_y rhs = div * bound_stress * d_bound.ravel("F") d = np.linalg.solve(a.todense(), -rhs) traction = stress * d + bound_stress * d_bound.ravel("F") traction_2d = traction.reshape((g.dim, -1), order="F") for cell in range(g.num_cells): fid, _, sgn = sps.find(g.cell_faces[:, cell]) self.assertTrue( np.all(np.sum(traction_2d[:, fid] * sgn, axis=1) < 1e-10) )
def solve_elliptic_problem(gb): for g, d in gb: if g.dim == 2: d['param'].set_source('flow', source(g, 0.0)) dir_bound = np.argwhere(g.has_face_tag(FaceTag.DOMAIN_BOUNDARY)) bc_cond = bc.BoundaryCondition(g, dir_bound, ['dir'] * dir_bound.size) d['param'].set_bc('flow', bc_cond) gb.add_edge_prop('param') for e, d in gb.edges_props(): g_h = gb.sorted_nodes_of_edge(e)[1] d['param'] = Parameters(g_h) flux = elliptic.EllipticModel(gb) p = flux.solve() flux.split('pressure') fvutils.compute_discharges(gb)
def solve_elliptic_problem(gb): for g, d in gb: if g.dim == 2: d['param'].set_source('flow', source(g, 0.0)) dir_bound = g.tags['domain_boundary_faces'].nonzero()[0] bc_cond = bc.BoundaryCondition(g, dir_bound, ['dir'] * dir_bound.size) d['param'].set_bc('flow', bc_cond) gb.add_edge_props('param') for e, d in gb.edges(): g_h = gb.nodes_of_edge(e)[1] d['param'] = Parameters(g_h) flux = elliptic.EllipticModel(gb) p = flux.solve() flux.split('pressure') fvutils.compute_discharges(gb)
def add_data_transport(gb): gb.add_node_props(["bc", "bc_val", "discharge", "apertures"]) for g, d in gb: b_faces = g.tags["domain_boundary_faces"].nonzero()[0] index = np.nonzero( abs(g.face_centers[:, b_faces]) == np.ones([3, b_faces.size]))[1] b_faces = b_faces[index] d["bc"] = bc.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size) d["bc_val"] = {"dir": np.ones(b_faces.size)} d["apertures"] = np.ones(g.num_cells) * np.power(.01, float(g.dim < 3)) d["discharge"] = upwind.Upwind().discharge( g, [1, 1, 2 * np.power(1000, g.dim < 2)], d["apertures"]) gb.add_edge_prop("discharge") for e, d in gb.edges_props(): g_h = gb.sorted_nodes_of_edge(e)[1] d["discharge"] = gb.node_prop(g_h, "discharge")
def add_data_transport(gb): gb.add_node_props(['bc', 'bc_val', 'discharge', 'apertures']) for g, d in gb: b_faces = g.tags['domain_boundary_faces'].nonzero()[0] index = np.nonzero( abs(g.face_centers[:, b_faces]) == np.ones([3, b_faces.size]))[1] b_faces = b_faces[index] d['bc'] = bc.BoundaryCondition(g, b_faces, ['dir'] * b_faces.size) d['bc_val'] = {'dir': np.ones(b_faces.size)} d['apertures'] = np.ones(g.num_cells) * np.power(.01, float(g.dim < 3)) d['discharge'] = upwind.Upwind().discharge( g, [1, 1, 2 * np.power(1000, g.dim < 2)], d['apertures']) gb.add_edge_prop('discharge') for e, d in gb.edges_props(): g_h = gb.sorted_nodes_of_edge(e)[1] d['discharge'] = gb.node_prop(g_h, 'discharge')
def add_data(g, advection): """ Define the permeability, apertures, boundary conditions """ b_faces = g.tags["domain_boundary_faces"].nonzero()[0] bnd = bc.BoundaryCondition(g, b_faces, ["dir"] * b_faces.size) bnd_val = np.zeros(g.num_faces) beta_n = advection.beta_n(g, [1, 0, 0]) kxx = 1e-2 * np.ones(g.num_cells) diffusion = second_order_tensor.SecondOrderTensorTensor(g.dim, kxx) f = np.ones(g.num_cells) * g.cell_volumes data = {"beta_n": beta_n, "bc": bnd, "bc_val": bnd_val, "k": diffusion, "f": f} return data
def test_zero_force(self): """ test that nothing moves if nothing is touched """ g = self.gb3d.grids_of_dimension(3)[0] data = {'param': Parameters(g)} bound = bc.BoundaryCondition(g, g.get_boundary_faces(), 'dir') data['param'].set_bc('mechanics', bound) solver = mpsa.FracturedMpsa() A, b = solver.matrix_rhs(g, data) u = np.linalg.solve(A.A, b) T = solver.traction(g, data, u) assert np.all(np.abs(u) < 1e-10) assert np.all(np.abs(T) < 1e-10)
def setup_2d_1d(nx, simplex_grid=False): frac1 = np.array([[0.2, 0.8], [0.5, 0.5]]) frac2 = np.array([[0.5, 0.5], [0.8, 0.2]]) fracs = [frac1, frac2] if not simplex_grid: gb = meshing.cart_grid(fracs, nx, physdims=[1, 1]) else: mesh_kwargs = {"mesh_size_frac": .2, "mesh_size_min": .02} domain = {"xmin": 0, "ymin": 0, "xmax": 1, "ymax": 1} gb = meshing.simplex_grid(fracs, domain, **mesh_kwargs) gb.compute_geometry() gb.assign_node_ordering() gb.add_node_props(["param"]) for g, d in gb: kxx = np.ones(g.num_cells) perm = tensor.SecondOrderTensor(3, kxx) a = 0.01 / np.max(nx) a = np.power(a, gb.dim_max() - g.dim) param = Parameters(g) param.set_tensor("flow", perm) param.set_aperture(a) if g.dim == 2: bound_faces = g.tags["domain_boundary_faces"].nonzero()[0] bound = bc.BoundaryCondition(g, bound_faces.ravel("F"), ["dir"] * bound_faces.size) bc_val = np.zeros(g.num_faces) bc_val[bound_faces] = g.face_centers[1, bound_faces] param.set_bc("flow", bound) param.set_bc_val("flow", bc_val) d["param"] = param gb.add_edge_props("kn") for e, d in gb.edges(): g = gb.nodes_of_edge(e)[0] mg = d["mortar_grid"] check_P = mg.low_to_mortar_avg() d["kn"] = 1 / (check_P * gb.node_props(g, "param").get_aperture()) return gb
def test_uniform_flow_cart_2d(): # Structured Cartesian grid g, perm = setup_cart_2d(np.array([10, 10])) bound_faces = np.argwhere( np.abs(g.cell_faces).sum(axis=1).A.ravel('F') == 1) bound = bc.BoundaryCondition(g, bound_faces.ravel('F'), ['dir'] * bound_faces.size) # Python inverter is most efficient for small problems flux, bound_flux = mpfa.mpfa(g, perm, bound, inverter='python') div = g.cell_faces.T a = div * flux pr_bound, pr_cell, gx, gy = setup_random_pressure_field(g) rhs = div * bound_flux * pr_bound pr = np.linalg.solve(a.todense(), -rhs) p_diff = pr - pr_cell assert np.max(np.abs(p_diff)) < 1e-8
def add_data(gb): """ Define the permeability, apertures, boundary conditions, source term """ gb.add_node_props(['param']) for g, d in gb: # initialize Parameter class params = data.Parameters(g) # Permeability kxx = np.ones(g.num_cells) if all(g.cell_centers[0, :] < 0.0001): perm = tensor.SecondOrder(3, kxx / 100, kxx, kxx) else: perm = tensor.SecondOrder(3, kxx * np.power(100, g.dim < 3)) params.set_tensor('flow', perm) # Source term params.set_source('flow', np.zeros(g.num_cells)) # Boundaries bound_faces = g.get_boundary_faces() top = np.argwhere(g.face_centers[1, :] > 1 - 1e-5) bot = np.argwhere(g.face_centers[1, :] < -1 + 1e-5) left = np.argwhere(g.face_centers[0, :] < -1 + 1e-5) dir_bound = np.concatenate((top, bot)) bound = bc.BoundaryCondition(g, dir_bound.ravel(), ['dir'] * dir_bound.size) d_bound = np.zeros(g.num_faces) d_bound[dir_bound] = g.face_centers[1, dir_bound] d_bound[left] = -1 * g.face_centers[0, left] params.set_bc('flow', bound) params.set_bc_val('flow', d_bound.ravel('F')) # Assign apertures params.apertures = np.ones(g.num_cells) * np.power(1e-2, 3 - g.dim) d['param'] = params
def setup_2d_1d(nx, simplex_grid=False): frac1 = np.array([[0.2, 0.8], [0.5, 0.5]]) frac2 = np.array([[0.5, 0.5], [0.8, 0.2]]) fracs = [frac1, frac2] if not simplex_grid: gb = meshing.cart_grid(fracs, nx, physdims=[1, 1]) else: mesh_kwargs = {'mesh_size_frac': .2, 'mesh_size_min': .02} domain = {'xmin': 0, 'ymin': 0, 'xmax': 1, 'ymax': 1} gb = meshing.simplex_grid(fracs, domain, **mesh_kwargs) gb.compute_geometry() gb.assign_node_ordering() gb.add_node_props(['param']) for g, d in gb: kxx = np.ones(g.num_cells) perm = tensor.SecondOrderTensor(3, kxx) a = 0.01 / np.max(nx) a = np.power(a, gb.dim_max() - g.dim) param = Parameters(g) param.set_tensor('flow', perm) param.set_aperture(a) if g.dim == 2: bound_faces = g.tags['domain_boundary_faces'].nonzero()[0] bound = bc.BoundaryCondition(g, bound_faces.ravel('F'), ['dir'] * bound_faces.size) bc_val = np.zeros(g.num_faces) bc_val[bound_faces] = g.face_centers[1, bound_faces] param.set_bc('flow', bound) param.set_bc_val('flow', bc_val) d['param'] = param gb.add_edge_props('kn') for e, d in gb.edges(): g = gb.nodes_of_edge(e)[0] d['kn'] = 1 / gb.node_props(g, 'param').get_aperture() return gb
def test_laplacian_stencil_cart_2d(): """ Apply MPFA on Cartesian grid, should obtain Laplacian stencil. """ # Set up 3 X 3 Cartesian grid g, perm = setup_cart_2d(np.array([3, 3])) bnd_faces = np.array([0, 3, 12]) bound = bc.BoundaryCondition(g, bnd_faces, ['dir'] * bnd_faces.size) # Python inverter is most efficient for small problems flux, bound_flux = mpfa.mpfa(g, perm, bound, inverter='python') div = g.cell_faces.T A = div * flux # Checks on interior cell mid = 4 assert A[mid, mid] == 4 assert A[mid - 1, mid] == -1 assert A[mid + 1, mid] == -1 assert A[mid - 3, mid] == -1 assert A[mid + 3, mid] == -1 # The first cell should have two Dirichlet bnds assert A[0, 0] == 6 assert A[0, 1] == -1 assert A[0, 3] == -1 # Cell 3 has one Dirichlet, one Neumann face assert A[2, 2] == 4 assert A[2, 1] == -1 assert A[2, 5] == -1 # Cell 2 has one Neumann face assert A[1, 1] == 3 assert A[1, 0] == -1 assert A[1, 2] == -1 assert A[1, 4] == -1 return A