def generate_2d_grid(self, n, xmax, ymax): g1 = pp.CartGrid([xmax * n, ymax * n], physdims=[xmax, ymax]) g1.compute_geometry() gb = pp.GridBucket() gb.add_nodes(g1) tol = 1e-6 left_faces = np.argwhere(g1.face_centers[1] > ymax - tol).ravel() right_faces = np.argwhere(g1.face_centers[1] < 0 + tol).ravel() val = np.ones(left_faces.size, dtype=np.bool) shape = [g1.num_faces, g1.num_faces] face_faces = sps.coo_matrix((val, (right_faces, left_faces)), shape=shape) gb.add_edge((g1, g1), face_faces) mg = pp.TensorGrid(np.linspace(0, xmax, n + 1)) mg.nodes[1] = ymax mg.compute_geometry() d_e = gb.edge_props((g1, g1)) d_e["mortar_grid"] = pp.BoundaryMortar(g1.dim - 1, mg, face_faces) gb.assign_node_ordering() return gb
def generate_grid_with_fractures(self, n, xmax, ymax): x = [xmax / 3] * 2 y = [0, ymax / 2] fracs = [np.array([x, y])] y = [ymax / 2, ymax] fracs.append(np.array([x, y])) gb = pp.meshing.cart_grid(fracs, [xmax * n, ymax * n], physdims=[xmax, ymax]) tol = 1e-6 for g, d in gb: # map right faces to left left = np.argwhere(g.face_centers[1] < tol).ravel() right = np.argwhere(g.face_centers[1] > ymax - tol).ravel() g.face_centers[1, right] = 0 g.left = left g.right = right # now create mappings between two grids of equal dimension for dim in [2, 1]: grids = gb.grids_of_dimension(dim) for i, gi in enumerate(grids): if gi.left.size < 1: continue for j, gj in enumerate(grids): if gj.right.size < 1: continue face_faces = self.match_grids(gi, gj) if np.sum(face_faces) == 0: continue gb.add_edge((gi, gj), face_faces) d_e = gb.edge_props((gi, gj)) di = gb.node_props(gi) dj = gb.node_props(gj) if di["node_number"] < dj["node_number"]: # gj is left g_m, _, _ = pp.partition.extract_subgrid(gj, gj.right, faces=True) face_faces = face_faces.T else: # gi is left g_m, _, _ = pp.partition.extract_subgrid(gi, gi.left, faces=True) side_g = {pp.grids.mortar_grid.LEFT_SIDE: g_m} d_e["mortar_grid"] = pp.BoundaryMortar( gi.dim - 1, side_g, face_faces) gb.compute_geometry() # basically reset g.face_centers[,right] gb.assign_node_ordering() return gb
def generate_grids(self, n, xmax, ymax, split): g1 = pp.CartGrid([split * n, ymax * n], physdims=[split, ymax]) g2 = pp.CartGrid([(xmax - split) * n, ymax * n], physdims=[xmax - split, ymax]) g2.nodes[0] += split g1.compute_geometry() g2.compute_geometry() grids = [g2, g1] gb = pp.GridBucket() [gb.add_nodes(g) for g in grids] [g2, g1] = gb.grids_of_dimension(2) tol = 1e-6 if np.any(g2.cell_centers[0] > split): right_grid = g2 left_grid = g1 else: right_grid = g1 left_grid = g2 gb.set_node_prop(left_grid, "node_number", 1) gb.set_node_prop(right_grid, "node_number", 0) left_faces = np.argwhere( left_grid.face_centers[0] > split - tol).ravel() right_faces = np.argwhere( right_grid.face_centers[0] < split + tol).ravel() val = np.ones(left_faces.size, dtype=np.bool) shape = [right_grid.num_faces, left_grid.num_faces] face_faces = sps.coo_matrix((val, (right_faces, left_faces)), shape=shape) gb.add_edge((right_grid, left_grid), face_faces) mg = pp.TensorGrid(np.array([split] * ((n + 1) * ymax))) mg.nodes[1] = np.linspace(0, ymax, (n + 1) * ymax) mg.compute_geometry() side_g = {pp.grids.mortar_grid.LEFT_SIDE: mg} d_e = gb.edge_props((g1, g2)) d_e["mortar_grid"] = pp.BoundaryMortar(g1.dim - 1, side_g, face_faces) d_e["edge_number"] = 0 return gb
def create_mortar_grids(gb): """ Given a grid bucket, create new edges (in the grid bucket) that maps the slave side of the fractures to the master side. Arguments: gb : GridBucket """ # First we add a edge from each grid to itself. for g, d in gb: # Define a mapping from faces to master and faces to slave master_id = g.frac_pairs[0] slave_id = g.frac_pairs[1] if master_id.size == 0: continue num_m = master_id.size if num_m != slave_id.size: raise ValueError("Mortar and slave side of fracture must match") rows = np.arange(num_m) master_face = sps.coo_matrix( (np.ones(num_m), (rows, master_id)), (num_m, g.num_faces) ).tocsc() slave_face = sps.coo_matrix( (np.ones(num_m), (rows, slave_id)), (num_m, g.num_faces) ).tocsc() # Find the mapping from slave to master slave_master = master_face.T * slave_face slave_grid, face_id, _ = pp.partition.extract_subgrid(g, slave_id, faces=True, is_planar=False) # do some checks that all mappings have been correct # Check that slave and master coincide if np.all(face_id != slave_id): raise AssertionError("Assume extract subgrid does not change ordering") if not np.all( [ np.allclose((slave_face - master_face) * g.face_centers[dim], 0) for dim in range(g.dim) ] ): raise AssertionError("Slave and master do not conside") if not np.all( [ np.allclose( slave_master.T * g.face_centers[dim], slave_face.T * g.face_centers[dim, slave_id] ) for dim in range(g.dim) ] ): raise AssertionError("Slave faces do not coinside with mortar cells") if not np.all( [ np.allclose( slave_face * g.face_centers[dim], slave_grid.cell_centers[dim] ) for dim in range(g.dim) ] ): raise AssertionError("Slave faces do not coinside with mortar cells") # Checks done. # Now create mortar grid mortar_grid = pp.BoundaryMortar(g.dim - 1, slave_grid, (slave_master.T)) # Add edge to Grid bucket gb.add_edge((g, g), slave_master) d_e = gb.edge_props((g, g)) d_e["mortar_grid"] = mortar_grid gb.assign_node_ordering()