def test_replace_2d_with_finer_pert(self): gb = self.setup_bucket(pert=True, include_1d=True) mg1, mg2 = self._mortar_grids(gb) proj_1_h = mg1.high_to_mortar_int.copy() proj_2_h = mg2.high_to_mortar_int.copy() proj_1_l = mg1.low_to_mortar_int.copy() proj_2_l = mg2.low_to_mortar_int.copy() gn = self.grid_2d_four_cells(pert=True) go = gb.grids_of_dimension(2)[0] mortars.replace_grids_in_bucket(gb, {go: gn}) mg1, mg2 = self._mortar_grids(gb) p1h = mg1.high_to_mortar_int.copy() p1l = mg1.low_to_mortar_int.copy() p2h = mg2.high_to_mortar_int.copy() p2l = mg2.low_to_mortar_int.copy() self.assertTrue((proj_1_l != p1l).nnz == 0) self.assertTrue((proj_2_h != p2h).nnz == 0) self.assertTrue(np.abs(p2l[0, 0] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[0, 1] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[1, 2] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[1, 3] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[2, 0] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[2, 1] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[3, 2] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[3, 3] - 0.5) < 1e-6) self.assertTrue(np.abs(p1h[0, 2] - 0.5) < 1e-6) self.assertTrue(np.abs(p1h[0, 4] - 0.5) < 1e-6) self.assertTrue(np.abs(p1h[1, 7] - 0.5) < 1e-6) self.assertTrue(np.abs(p1h[1, 8] - 0.5) < 1e-6)
def test_replace_by_same(self): # 1x2 grid. # Copy the higher dimensional grid and replace. The mapping should be # the same. f1 = np.array([[0, 1], [.5, .5]]) N = [1, 2] gb = meshing.cart_grid([f1], N, **{"physdims": [1, 1]}) gb.compute_geometry() # Pick out mortar grid by a loop, there is only one edge in the bucket for e, d in gb.edges(): mg = d["mortar_grid"] old_projection = mg.high_to_mortar_int.copy() g_old = gb.grids_of_dimension(2)[0] g_new = g_old.copy() mortars.replace_grids_in_bucket(gb, {g_old: g_new}) # Get mortar grid again for e, d in gb.edges(): mg = d["mortar_grid"] new_projection = mg.high_to_mortar_int # The projections should be identical self.assertTrue((old_projection != new_projection).nnz == 0)
def setup(self, remove_tags=False, num_1d=3, pert_node=False): g2 = self.grid_2d() g1 = self.grid_1d() gb = meshing._assemble_in_bucket([[g2], [g1]]) gb.add_edge_props("face_cells") for e, d in gb.edges(): a = np.zeros((g2.num_faces, g1.num_cells)) a[2, 1] = 1 a[3, 0] = 1 a[7, 0] = 1 a[8, 1] = 1 d["face_cells"] = sps.csc_matrix(a.T) meshing.create_mortar_grids(gb) g_new_2d = self.grid_2d(pert_node) g_new_1d = self.grid_1d(num_1d) mortars.replace_grids_in_bucket(gb, g_map={g2: g_new_2d, g1: g_new_1d}) # if remove_tags: # internal_flag = FaceTag.FRACTURE # [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb] gb.assign_node_ordering() self.set_params(gb) return gb
def test_refine_distort_high_dim(self): # Replace the 2d grid with a finer one, and move the nodes along the # interface so that areas along the interface are no longer equal. f1 = np.array([[0, 1], [.5, .5]]) N = [1, 2] gb = meshing.cart_grid([f1], N, **{"physdims": [1, 1]}) gb.compute_geometry() # Pick out mortar grid by a loop, there is only one edge in the bucket for e, d in gb.edges(): mg = d["mortar_grid"] old_projection = mg.high_to_mortar_int.copy() g_old = gb.grids_of_dimension(2)[0] # Create a new, finer 2d grid. This is the simplest # way to put the fracture in the right place is to create a new # bucket, and pick out the higher dimensional grid gb_new = meshing.cart_grid([f1], [2, 2], **{"physdims": [1, 1]}) gb_new.compute_geometry() g_new = gb_new.grids_of_dimension(2)[0] # By construction of the split grid, we know that the nodes at # (0.5, 0.5) are no 5 and 6, and that no 5 is associated with the # face belonging to the lower cells. # Move node belonging to the lower face g_new.nodes[0, 5] = 0.2 g_new.nodes[0, 6] = 0.7 g_new.compute_geometry() mortars.replace_grids_in_bucket(gb, {g_old: g_new}) # Get mortar grid again for e, d in gb.edges(): mg = d["mortar_grid"] new_projection = mg.high_to_mortar_int # Check shape self.assertTrue(new_projection.shape[0] == old_projection.shape[0]) self.assertTrue(new_projection.shape[1] == g_new.num_faces) # Projection sums to unity. self.assertTrue(np.all(new_projection.toarray().sum(axis=1) == 1)) fi = np.where(g_new.face_centers[1] == 0.5)[0] self.assertTrue(fi.size == 4) # Hard coded test (based on knowledge of how the grids and meshing # is implemented). Faces to the uppermost cell are always kept in # place, the lowermost are duplicated towards the end of the face # definition. self.assertTrue(np.abs(new_projection[0, 8] - 0.7 < 1e-6)) self.assertTrue(np.abs(new_projection[0, 9] - 0.3 < 1e-6)) self.assertTrue(np.abs(new_projection[1, 12] - 0.2 < 1e-6)) self.assertTrue(np.abs(new_projection[1, 13] - 0.8 < 1e-6))
def test_coarsen_high_dim(self): # Replace the 2d grid with a coarser one f1 = np.array([[0, 1], [.5, .5]]) N = [2, 2] gb = meshing.cart_grid([f1], N, **{"physdims": [1, 1]}) gb.compute_geometry() # Pick out mortar grid by a loop, there is only one edge in the bucket for e, d in gb.edges(): mg = d["mortar_grid"] old_projection = mg.high_to_mortar_int.copy() g_old = gb.grids_of_dimension(2)[0] # Create a new, coarser 2d grid. This is the simplest # way to put the fracture in the right place is to create a new # bucket, and pick out the higher dimensional grid gb_new = meshing.cart_grid([f1], [1, 2], **{"physdims": [1, 1]}) gb_new.compute_geometry() g_new = gb_new.grids_of_dimension(2)[0] mortars.replace_grids_in_bucket(gb, {g_old: g_new}) # Get mortar grid again for e, d in gb.edges(): mg = d["mortar_grid"] new_projection = mg.high_to_mortar_int # Check shape self.assertTrue(new_projection.shape[0] == old_projection.shape[0]) self.assertTrue(new_projection.shape[1] == g_new.num_faces) # Projection sums to unity. self.assertTrue(np.all(new_projection.toarray().sum(axis=1) == 1)) fi = np.where(g_new.face_centers[1] == 0.5)[0] self.assertTrue(fi.size == 2) # Hard coded test (based on knowledge of how the grids and meshing # is implemented). Faces to the uppermost cell are always kept in # place, the lowermost are duplicated towards the end of the face # definition. self.assertTrue(np.all(new_projection[0, fi[0]] == 1)) self.assertTrue(np.all(new_projection[1, fi[0]] == 1)) self.assertTrue(np.all(new_projection[2, fi[1]] == 1)) self.assertTrue(np.all(new_projection[3, fi[1]] == 1))
def test_replace_2d_with_identity_no_1d(self): gb = self.setup_bucket(pert=False, include_1d=False) mg1, mg2 = self._mortar_grids(gb) proj_2_h = mg2.high_to_mortar_int.copy() proj_2_l = mg2.low_to_mortar_int.copy() gn = self.grid_2d_two_cells() go = gb.grids_of_dimension(2)[0] mortars.replace_grids_in_bucket(gb, {go: gn}) mg1, mg2 = self._mortar_grids(gb) p2h = mg2.high_to_mortar_int.copy() p2l = mg2.low_to_mortar_int.copy() self.assertTrue((proj_2_h != p2h).nnz == 0) self.assertTrue((proj_2_l != p2l).nnz == 0)
def test_replace_1d_with_identity(self): gb = self.setup_bucket(pert=False) mg1, mg2 = self._mortar_grids(gb) proj_1_h = mg1.high_to_mortar_int.copy() proj_1_l = mg1.low_to_mortar_int.copy() gn = self.grid_1d(2) go = gb.grids_of_dimension(1)[0] mortars.replace_grids_in_bucket(gb, {go: gn}) mg1, mg2 = self._mortar_grids(gb) p1h = mg1.high_to_mortar_int.copy() p1l = mg1.low_to_mortar_int.copy() self.assertTrue((proj_1_h != p1h).nnz == 0) self.assertTrue((proj_1_l != p1l).nnz == 0)
def test_replace_2d_with_finer_no_1d(self): gb = self.setup_bucket(pert=False, include_1d=False) mg1, mg2 = self._mortar_grids(gb) proj_2_h = mg2.high_to_mortar_int.copy() gn = self.grid_2d_four_cells_no_1d() go = gb.grids_of_dimension(2)[0] mortars.replace_grids_in_bucket(gb, {go: gn}) mg1, mg2 = self._mortar_grids(gb) p2h = mg2.high_to_mortar_int.copy() p2l = mg2.low_to_mortar_int.copy() self.assertTrue((proj_2_h != p2h).nnz == 0) self.assertTrue(np.abs(p2l[0, 0] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[0, 1] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[1, 2] - 0.5) < 1e-6) self.assertTrue(np.abs(p2l[1, 3] - 0.5) < 1e-6)
def create_gb(cells_2d, alpha_1d=None, alpha_mortar=None): mesh_size = np.sqrt(2 / cells_2d) mesh_kwargs = { "tol": tol(), "mesh_size_frac": mesh_size, "mesh_size_min": mesh_size / 20, } mesh_kwargs = {"mesh_size_frac": mesh_size, "mesh_size_min": mesh_size / 20} file_name = "example_1_split.csv" gb = pp.importer.dfm_2d_from_csv(file_name, mesh_kwargs, domain()) g_map = {} if alpha_1d is not None: for g, d in gb: if g.dim == 1: num_nodes = int(g.num_nodes * alpha_1d) g_map[g] = refinement.remesh_1d(g, num_nodes=num_nodes) g_map[g].compute_geometry() mg_map = {} if alpha_mortar is not None: for e, d in gb.edges(): mg = d["mortar_grid"] if mg.dim == 1: mg_map[mg] = {} for s, g in mg.side_grids.items(): num_nodes = int(g.num_nodes * alpha_mortar) mg_map[mg][s] = refinement.remesh_1d(g, num_nodes=num_nodes) gb = mortars.replace_grids_in_bucket(gb, g_map, mg_map, tol()) gb.assign_node_ordering() return gb
gmap = {} for go in gb.grids_of_dimension(2): for gn in gb_new.grids_of_dimension(2): if gn.frac_num == go.frac_num: gmap[go] = gn xf = gn.face_centers hit = np.logical_or( np.any(np.abs(xf - dom_min) < tol, axis=0), np.any(np.abs(xf - dom_max) < tol, axis=0), ) domain_tag = FaceTag.DOMAIN_BOUNDARY gn.remove_face_tag_if_tag(domain_tag, domain_tag) gn.add_face_tag(np.where(hit)[0], domain_tag) mortars.replace_grids_in_bucket(gb, gmap) if VEM: internal_flag = FaceTag.FRACTURE [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb] if True: # select the permeability depending on the selected test case if test_case == 1: kf = 1e4 else: kf = 1e-4 data_problem = { "domain": domain, "tol": tol, "aperture": 1e-4,
def test_permute_perturb_nodes_in_replacement_grid(self): # Replace higher dimensional grid with an identical one, except the # node indices are perturbed. This will test sorting of nodes along # 1d lines. Also perturb nodes along the segment. f1 = np.array([[0, 1], [.5, .5]]) N = [2, 2] gb = meshing.cart_grid([f1], N, **{"physdims": [1, 1]}) gb.compute_geometry() # Pick out mortar grid by a loop, there is only one edge in the bucket for e, d in gb.edges(): mg = d["mortar_grid"] old_projection = mg.high_to_mortar_int.copy() g_old = gb.grids_of_dimension(2)[0] # Create a new, finer 2d grid. This is the simplest # way to put the fracture in the right place is to create a new # bucket, and pick out the higher dimensional grid gb_new = meshing.cart_grid([f1], [2, 2], **{"physdims": [1, 1]}) gb_new.compute_geometry() g_new = gb_new.grids_of_dimension(2)[0] # By construction of the split grid, we know that the nodes at # (0.5, 0.5) are no 5 and 6, and that no 5 is associated with the # face belonging to the lower cells. # Replacements: along lower segment (3, 5, 7) -> (7, 5, 3) # On upper segment: (4, 6, 8) -> (8, 4, 6) g_new.nodes[0, 3] = 1 g_new.nodes[0, 4] = 0.7 g_new.nodes[0, 5] = 0.2 g_new.nodes[0, 6] = 1 g_new.nodes[0, 7] = 0 g_new.nodes[0, 8] = 0 fn = g_new.face_nodes.indices.reshape((2, g_new.num_faces), order="F") fn[:, 8] = np.array([4, 8]) fn[:, 9] = np.array([4, 6]) fn[:, 12] = np.array([7, 5]) fn[:, 13] = np.array([5, 3]) mortars.replace_grids_in_bucket(gb, {g_old: g_new}) # Get mortar grid again for e, d in gb.edges(): mg = d["mortar_grid"] new_projection = mg.high_to_mortar_int # Check shape self.assertTrue(new_projection.shape[0] == old_projection.shape[0]) self.assertTrue(new_projection.shape[1] == g_new.num_faces) # Projection sums to unity. self.assertTrue(np.all(new_projection.toarray().sum(axis=1) == 1)) fi = np.where(g_new.face_centers[1] == 0.5)[0] self.assertTrue(fi.size == 4) # Hard coded test (based on knowledge of how the grids and meshing # is implemented). Faces to the uppermost cell are always kept in # place, the lowermost are duplicated towards the end of the face # definition. # It seems the mortar grid is designed so that the first cell is # associated with face 9 in the old grid. This is split into 2/5 face # 8 and 3/5 face 9. self.assertTrue(np.abs(new_projection[0, 8] - 0.4 < 1e-6)) self.assertTrue(np.abs(new_projection[0, 9] - 0.6 < 1e-6)) # The second cell in mortar grid is still fully connected to face 9 self.assertTrue(np.abs(new_projection[1, 9] - 1 < 1e-6)) self.assertTrue(np.abs(new_projection[2, 13] - 1 < 1e-6)) self.assertTrue(np.abs(new_projection[3, 12] - 0.4 < 1e-6)) self.assertTrue(np.abs(new_projection[3, 13] - 0.6 < 1e-6))
def setup( self, num_fracs=1, remove_tags=False, alpha_1d=None, alpha_mortar=None, alpha_2d=None, ): domain = {"xmin": 0, "xmax": 1, "ymin": 0, "ymax": 1} if num_fracs == 0: p = np.zeros((2, 0)) elif num_fracs == 1: p = [np.array([[0, 1], [0.5, 0.5]])] # p = [np.array([[0.5, 0.5], [0, 1]])] elif num_fracs == 2: p = [ np.array([[0, 0.5], [0.5, 0.5]]), np.array([[0.5, 1], [0.5, 0.5]]), np.array([[0.5, 0.5], [0, 0.5]]), np.array([[0.5, 0.5], [0.5, 1]]), ] mesh_size = {"value": 0.3, "bound_value": 0.3} gb = meshing.simplex_grid(fracs=p, domain=domain, mesh_size=mesh_size, verbose=0) # gb = meshing.cart_grid([np.array([[0.5, 0.5], [0, 1]])],np.array([10, 10]), # physdims=np.array([1, 1])) gmap = {} # Refine 2D grid? if alpha_2d is not None: mesh_size = { "value": 0.3 * alpha_2d, "bound_value": 0.3 * alpha_2d } gbn = meshing.simplex_grid(fracs=p, domain=domain, mesh_size=mesh_size, verbose=0) go = gb.grids_of_dimension(2)[0] gn = gbn.grids_of_dimension(2)[0] gn.compute_geometry() gmap[go] = gn # Refine 1d grids if alpha_1d is not None: for g, d in gb: if g.dim == 1: if alpha_1d > 1: num_nodes = 1 + int(alpha_1d) * g.num_cells else: num_nodes = 1 + int(alpha_1d * g.num_cells) num_nodes = 1 + int(alpha_1d * g.num_cells) gmap[g] = refinement.remesh_1d(g, num_nodes=num_nodes) gmap[g].compute_geometry() # Refine mortar grid mg_map = {} if alpha_mortar is not None: for e, d in gb.edges(): mg = d["mortar_grid"] if mg.dim == 1: mg_map[mg] = {} for s, g in mg.side_grids.items(): num_nodes = int(g.num_nodes * alpha_mortar) mg_map[mg][s] = refinement.remesh_1d( g, num_nodes=num_nodes) gb = mortars.replace_grids_in_bucket(gb, gmap, mg_map, tol=1e-4) # if remove_tags: # internal_flag = FaceTag.FRACTURE # [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb] gb.assign_node_ordering() self.set_params(gb) return gb