def test_rot_poly(self): poly = np.array([[1, 0, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1]]).T p = np.array( [ [0, 0, 0], [0, 0.5, 0.5], [2, 0.5, 0.5], [0, 0, 0.5], [0, -1, 0.5], [1, 0, 0], [1, 0.5, 0.5], ] ).T d, cp, in_poly = cg.dist_points_polygon(p, poly) known_d = np.array([1, 1, 1, 1, np.sqrt(2), 0, 0]) known_cp = np.array( [ [1, 0, 0], [1, 0.5, 0.5], [1, 0.5, 0.5], [1, 0, 0.5], [1, 0, 0.5], [1, 0, 0], [1, 0.5, 0.5], ] ).T self.assertTrue(np.allclose(d, known_d)) self.assertTrue(np.allclose(cp, known_cp))
def test_norot_poly(self): poly = np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]).T p = np.array([[0.5, 0.5, 0], [0.5, 0, 0], [0.5, 0.5, 1], [0, 0, 1], [0.5, 0, 1], [2, 0.5, 0], [2, 0, 1]]).T d, cp, in_poly = cg.dist_points_polygon(p, poly) known_d = np.array([0, 0, 1, 1, 1, 1, np.sqrt(2)]) known_cp = np.array([[0.5, 0.5, 0], [0.5, 0, 0], [0.5, 0.5, 0], [0, 0, 0], [0.5, 0, 0], [1, 0.5, 0], [1, 0, 0]]).T assert np.allclose(d, known_d) assert np.allclose(cp, known_cp)
def test_rot_poly(self): poly = np.array([[1, 0, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1]]).T p = np.array([[0, 0, 0], [0, 0.5, 0.5], [2, 0.5, 0.5], [0, 0, 0.5], [0, -1, 0.5], [1, 0, 0], [1, 0.5, 0.5]]).T d, cp, in_poly = cg.dist_points_polygon(p, poly) known_d = np.array([1, 1, 1, 1, np.sqrt(2), 0, 0]) known_cp = np.array([[1, 0, 0], [1, 0.5, 0.5], [1, 0.5, 0.5], [1, 0, 0.5], [1, 0, 0.5], [1, 0, 0], [1, 0.5, 0.5]]).T known_inp = np.array([0, 1, 0, 0, 0, 0, 1], dtype=np.bool) assert np.allclose(d, known_d) assert np.allclose(cp, known_cp)
def dfn(fracs, conforming, intersections=None, keep_geo=False, tol=1e-4, **kwargs): """ Create a mesh of a DFN model, that is, only of fractures. The mesh can eihter be conforming along fracture intersections, or each fracture is meshed independently. The latter case will typically require some sort of sewing together external to this funciton. TODO: What happens if we give in a non-connected network? Parameters: fracs (either Fractures, or a FractureNetwork). conforming (boolean): If True, the mesh will be conforming along 1d intersections. intersections (list of lists, optional): Each item corresponds to an intersection between two fractures. In each sublist, the first two indices gives fracture ids (refering to order in fracs). The third item is a numpy array representing intersection coordinates. If no intersections provided, intersections will be detected using function in FractureNetwork. **kwargs: Parameters passed to gmsh. Returns: GridBucket (if conforming is True): Mixed-dimensional mesh that represents all fractures, and intersection poitns and line. """ if isinstance(fracs, FractureNetwork) \ or isinstance(fracs, FractureNetwork_full): network = fracs else: network = FractureNetwork(fracs) # Populate intersections in FractureNetowrk, or find intersections if not # provided. if intersections is not None: logger.warn('FractureNetwork use pre-computed intersections') network.intersections = [Intersection(*i) for i in intersections] else: logger.warn('FractureNetwork find intersections in DFN') tic = time.time() network.find_intersections() logger.warn('Done. Elapsed time ' + str(time.time() - tic)) if conforming: logger.warn('Create conforming mesh for DFN network') grids = simplex.triangle_grid_embedded(network, find_isect=False, **kwargs) else: logger.warn('Create non-conforming mesh for DFN network') tic = time.time() grid_list = [] neigh_list = [] for fi in range(len(network._fractures)): logger.info('Meshing of fracture ' + str(fi)) # Rotate fracture vertexes and intersection points fp, ip, other_frac, rot, cp = network.fracture_to_plane(fi) frac_i = network[fi] f_lines = np.reshape(np.arange(ip.shape[1]), (2, -1), order='F') frac_dict = {'points': ip, 'edges': f_lines} if keep_geo: file_name = 'frac_mesh_' + str(fi) kwargs['file_name'] = file_name # Create mesh on this fracture surface. grids = simplex.triangle_grid(frac_dict, fp, verbose=False, **kwargs) irot = rot.T # Loop over grids, rotate back again to 3d coordinates for gl in grids: for g in gl: g.nodes = irot.dot(g.nodes) + cp # Nodes of main (fracture) grid, in 3d coordinates1 main_nodes = grids[0][0].nodes main_global_point_ind = grids[0][0].global_point_ind # Loop over intersections, check if the intersection is on the # boundary of this fracture. for ind, isect in enumerate(network.intersections_of_fracture(fi)): of = isect.get_other_fracture(frac_i) if isect.on_boundary_of_fracture(frac_i): dist, _, _ = cg.dist_points_polygon(main_nodes, of.p) hit = np.argwhere(dist < tol).reshape((1, -1))[0] nodes_1d = main_nodes[:, hit] global_point_ind = main_global_point_ind[hit] assert cg.is_collinear(nodes_1d, tol=tol) sort_ind = cg.argsort_point_on_line(nodes_1d, tol=tol) g_aux = TensorGrid(np.arange(nodes_1d.shape[1])) g_aux.nodes = nodes_1d[:, sort_ind] g_aux.global_point_ind = global_point_ind[sort_ind] grids[1].insert(ind, g_aux) assert len(grids[0]) == 1, 'Fracture should be covered by single'\ 'mesh' grid_list.append(grids) neigh_list.append(other_frac) logger.warn('Finished creating grids. Elapsed time ' + str(time.time() - tic)) logger.warn('Merge grids') tic = time.time() grids = non_conforming.merge_grids(grid_list, neigh_list) logger.warn('Done. Elapsed time ' + str(time.time() - tic)) for g_set in grids: if len(g_set) > 0: s = 'Created ' + str(len(g_set)) + ' ' + str(g_set[0].dim) + \ '-d grids with ' num = 0 for g in g_set: num += g.num_cells s += str(num) + ' cells' logger.info(s) return grid_list_to_grid_bucket(grids, check_highest_dim=False)