def test_conforming_two_fractures(self): f_1 = pp.Fracture( np.array([[-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0]]).T) f_2 = pp.Fracture( np.array([[-1, 0, -1], [1, 0, -1], [1, 0, 1], [-1, 0, 1]]).T) network = pp.FractureNetwork3d([f_1, f_2]) mesh_args = { "mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network.mesh(mesh_args, dfn=True)
def test_one_to_boundary_3d(self): """ One fracture in 3d going all the way to the boundary """ f_1 = np.array([[1, 5, 5, 1], [1, 1, 1, 1], [1, 1, 3, 3]]) f_set = [pp.Fracture(f_1)] domain = {"xmin": 0, "ymin": 0, "zmin": 0, "xmax": 5, "ymax": 5, "zmax": 5} mesh_size_min = 0.1 mesh_size_frac = 0.1 mesh_size_bound = 2 on_boundary = np.array( [False, False, False, False, True, True, True, True, True, True, True, True] ) network = pp.FractureNetwork3d(f_set) network.impose_external_boundary(domain) network.find_intersections() network.split_intersections() network._insert_auxiliary_points( mesh_size_frac=mesh_size_frac, mesh_size_min=mesh_size_min, mesh_size_bound=mesh_size_bound, ) mesh_size = network._determine_mesh_size(boundary_point_tags=on_boundary) decomp = network.decomposition # Many of the points should have mesh size of 2, adjust the exceptions below mesh_size_known = np.full( decomp["points"].shape[1], mesh_size_bound, dtype=np.float ) # Find the points on the fracture fracture_poly = np.where(np.logical_not(network.tags["boundary"]))[0] self.assertTrue(fracture_poly.size == 1) fracture_points = decomp["polygons"][fracture_poly[0]][0] # These should have been assigned fracture mesh size mesh_size_known[fracture_points] = mesh_size_frac # Two of the domain corners are close enough to the fracture to have their # mesh size modified from the default boundary value origin = np.zeros((3, 1)) _, ind = pp.utils.setmembership.ismember_rows(origin, decomp["points"]) mesh_size_known[ind] = np.sqrt(3) corner = np.array([5, 0, 0]).reshape((3, 1)) _, ind = pp.utils.setmembership.ismember_rows( corner, decomp["points"], sort=False ) mesh_size_known[ind] = np.sqrt(2) self.assertTrue(np.all(np.isclose(mesh_size, mesh_size_known)))
def test_issue_90(self): f_1 = pp.Fracture( np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]).T) f_2 = pp.Fracture(np.array([[0, 0, 1], [0, 0, -1], [1, 1, -1]]).T) mesh_args = { "mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2]) network.mesh(mesh_args)
def test_T_intersection_within_plane(self, **kwargs): f_1 = pp.Fracture(np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]).T) f_2 = pp.Fracture(np.array([[0.5, 0.5, 1], [0.5, 0.5, 0], [0.5, 0.9, 0.0]]).T) domain = {"xmin": -1, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -1, "zmax": 2} # This test, when used with certain versions of gmsh (<2.15?) gives # a mismatch between 2d cells and 3d faces on fracture surfaces. The bug # can be located in the .msh-file. To function as a test, we disband the # test of cell-face relations. mesh_args = {"mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2} network = pp.FractureNetwork3d([f_1, f_2], domain=domain) network.mesh(mesh_args)
def test_one_fracture_touching_two_opposing_boundaries(self): """ Two fractures intersecting along a line. The example also sets different characteristic mesh lengths on the boundary and at the fractures. """ f_1 = pp.Fracture(np.array([[-2, 2, 2, -2], [0, 0, 0, 0], [-1, -1, 1, 1]])) mesh_args, domain = self.kwarguments_and_domain() network = pp.FractureNetwork3d([f_1], domain) network.mesh(mesh_args)
def test_three_fractures_sharing_line_same_segment(self, **kwargs): """ Three fractures that all share an intersection line. This can be considered as three intersection lines that coincide. """ f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture(np.array([[-1, 1, 1, -1], [-1, 1, 1, -1], [-1, -1, 1, 1]])) f_3 = pp.Fracture(np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-1, -1, 1, 1]])) domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} mesh_args = {"mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2} network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) network.mesh(mesh_args)
def test_issue_58_3(self): domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} mesh_args = { "mesh_size_frac": 0.5, "mesh_size_bound": 1, "mesh_size_min": 0.2, "return_expected": True, } f_1 = pp.Fracture(np.array([[0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]])) f_2 = pp.Fracture(np.array([[0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 1, 1]])) network = pp.FractureNetwork3d([f_1, f_2], domain=domain) network.mesh(mesh_args)
def test_three_intersecting_fractures(self, **kwargs): """ Three fractures intersecting, with intersecting intersections (point) """ f_1 = pp.Fracture( np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-0.7, -0.7, 0.8, 0.8]])) f_3 = pp.Fracture( np.array([[-1, 1, 1, -1], [-1, -1, 1, 1], [0, 0, 0, 0]])) # Add some parameters for grid size domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } mesh_args = { "mesh_size_frac": 0.5, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) gb = network.mesh(mesh_args) isect_0_coord = np.array([[0, 0], [0, 0], [-0.7, 0.8]]) isect_1_coord = np.array([[-1, 1], [0, 0], [0, 0]]) isect_2_coord = np.array([[0, 0], [-1, 1], [0, 0]]) isect_0 = IntersectionInfo(0, 1, isect_0_coord) isect_1 = IntersectionInfo(0, 2, isect_1_coord) isect_2 = IntersectionInfo(1, 2, isect_2_coord) isect_pt = np.array([0, 0, 0]).reshape((-1, 1)) self.check_gb( gb, domain, fractures=[f_1, f_2, f_3], isect_line=[isect_0, isect_1, isect_2], isect_pt=[isect_pt], expected_num_1d_grids=6, expected_num_0d_grids=1, )
def test_fracture_cut_not_split_by_domain(self): self.setUp() f_1 = pp.Fracture( np.array([[-1, 2, 2, -1], [0.5, 0.5, 0.5, 0.5], [-1, -1, 0.7, 0.7]])) network = pp.FractureNetwork3d(f_1, domain=self.non_convex_polyhedron) mesh_args = { "mesh_size_bound": 1, "mesh_size_frac": 1, "mesh_size_min": 0.1 } gb = network.mesh(mesh_args) self.assertTrue(len(gb.grids_of_dimension(2)) == 1)
def setup(self, num_fracs=1, remove_tags=False): domain = { "xmin": 0, "xmax": 1, "ymin": 0, "ymax": 1, "zmin": 0, "zmax": 1 } if num_fracs == 0: fl = [] elif num_fracs == 1: fl = [ pp.Fracture( np.array([[0, 1, 1, 0], [0.5, 0.5, 0.5, 0.5], [0, 0, 1, 1]])) ] elif num_fracs == 2: fl = [ pp.Fracture( np.array([[0, 1, 1, 0], [0.5, 0.5, 0.5, 0.5], [0, 0, 1, 1]])), pp.Fracture( np.array([[0.5, 0.5, 0.5, 0.5], [0, 1, 1, 0], [0, 0, 1, 1]])), ] elif num_fracs == 3: fl = [ pp.Fracture( np.array([[0, 1, 1, 0], [0.5, 0.5, 0.5, 0.5], [0, 0, 1, 1]])), pp.Fracture( np.array([[0.5, 0.5, 0.5, 0.5], [0, 1, 1, 0], [0, 0, 1, 1]])), pp.Fracture( np.array([[0, 1, 1, 0], [0, 0, 1, 1], [0.5, 0.5, 0.5, 0.5]])), ] network = pp.FractureNetwork3d(fl, domain) mesh_args = {"mesh_size_frac": 0.5, "mesh_size_min": 0.5} gb = network.mesh(mesh_args) self.set_params(gb) return gb
def test_unstruct_tetrahedron(self): box = {"xmin": 0, "xmax": 1, "ymin": 0, "ymax": 1, "zmin": 0, "zmax": 1} network = pp.FractureNetwork3d([], domain=box) mesh_args = {"mesh_size_frac": 3, "mesh_size_min": 3} gb = network.mesh(mesh_args) g = gb.grids_of_dimension(3)[0] c = pp.FourthOrderTensor(np.ones(g.num_cells), np.ones(g.num_cells)) robin_weight = 1.0 bot = g.face_centers[2] < 1e-10 top = g.face_centers[2] > 1 - 1e-10 west = g.face_centers[0] < 1e-10 east = g.face_centers[0] > 1 - 1e-10 north = g.face_centers[1] > 1 - 1e-10 south = g.face_centers[1] < 1e-10 dir_ind = np.ravel(np.argwhere(west + top)) neu_ind = np.ravel(np.argwhere(bot)) rob_ind = np.ravel(np.argwhere(east + north + south)) names = ["dir"] * len(dir_ind) + ["rob"] * len(rob_ind) bnd_ind = np.hstack((dir_ind, rob_ind)) bnd = pp.BoundaryConditionVectorial(g, bnd_ind, names) def u_ex(x): return np.vstack((x[1], x[0], 0 * x[2])) def T_ex(faces): if np.size(faces) == 0: return np.atleast_2d(np.array([])) sigma = np.array([[0, 2, 0], [2, 0, 0], [0, 0, 0]]) T_r = [np.dot(sigma, g.face_normals[:, f]) for f in faces] return np.vstack(T_r).T u_bound = np.zeros((3, g.num_faces)) sgn_n = g.sign_of_faces(neu_ind) sgn_r = g.sign_of_faces(rob_ind) u_bound[:, dir_ind] = u_ex(g.face_centers[:, dir_ind]) u_bound[:, neu_ind] = T_ex(neu_ind) * sgn_n u_bound[:, rob_ind] = ( T_ex(rob_ind) * sgn_r + robin_weight * u_ex(g.face_centers[:, rob_ind]) * g.face_areas[rob_ind] ) u, T = self.solve_mpsa(g, c, robin_weight, bnd, u_bound) self.assertTrue(np.allclose(u, u_ex(g.cell_centers).ravel("F"))) self.assertTrue(np.allclose(T, T_ex(np.arange(g.num_faces)).ravel("F")))
def test_sinle_fracture_aligned_with_axis(self): # Test of method FractureNetwork.bounding_box() to inquire about # network extent f1 = pp.Fracture(np.array([[0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]]), check_convexity=False) network = pp.FractureNetwork3d([f1]) d = network.bounding_box() self.assertTrue(d["xmin"] == 0) self.assertTrue(d["xmax"] == 1) self.assertTrue(d["ymin"] == 0) self.assertTrue(d["ymax"] == 1) self.assertTrue(d["zmin"] == 0) self.assertTrue(d["zmax"] == 0)
def test_three_fractures_split_segments(self, **kwargs): """ Three fractures that all intersect along the same line, but with the intersection between two of them forming an extension of the intersection of all three. """ f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[-1, 1, 1, -1], [-1, 1, 1, -1], [-0.5, -0.5, 0.5, 0.5]]) ) f_3 = pp.Fracture(np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-1, -1, 1, 1]])) domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} mesh_args = {"mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2} network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) network.mesh(mesh_args)
def test_one_fracture_intersected_by_two(self, **kwargs): """ One fracture, intersected by two other (but no point intersections) """ f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-0.7, -0.7, 0.8, 0.8]]) ) f_3 = pp.Fracture(f_2.p + np.array([0.5, 0, 0]).reshape((-1, 1))) # Add some parameters for grid size domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} mesh_args = {"mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2} network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) network.mesh(mesh_args)
def create_grid() -> Tuple[pp.Grid, dict, dict]: """ Ivar ex3 grid""" # Define the three fractures n_points = 16 # Injection f_1 = pp.EllipticFracture( np.array([10, 3.5, -3]), 11, 18, 0.5, 0, 0, num_points=n_points, ) f_2 = pp.EllipticFracture( np.array([1, 5, 1]), 15, 10, np.pi * 0, np.pi / 4.0, np.pi / 2.0, num_points=n_points, ) # Production f_3 = pp.EllipticFracture( np.array([-13, 0, 0]), 20, 10, 0.5, np.pi / 3, np.pi / 1.6, num_points=n_points, ) fractures = [f_1, f_2, f_3] # Define the domain size = 50 box = { "xmin": -size, "xmax": size, "ymin": -size, "ymax": size, "zmin": -size, "zmax": size, } mesh_size = 3.2 mesh_args = { "mesh_size_frac": mesh_size, "mesh_size_min": 0.5 * mesh_size, "mesh_size_bound": 3 * mesh_size, } # Make a fracture network network = pp.FractureNetwork3d(fractures, domain=box) # Generate the mixed-dimensional mesh gb = network.mesh(mesh_args) return gb, box, mesh_args
def test_no_fracture(self): domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } network = pp.FractureNetwork3d(domain=domain) mesh_args = { "mesh_size_bound": 1, "mesh_size_frac": 1, "mesh_size_min": 0.1 } gb = network.mesh(mesh_args) self.check_gb(gb, domain)
def setup(tail_folders): """ Setup method. Set up a fracture network and mesh it. """ pth = Path(os.path.abspath(__file__)) root = pth.parent / tail_folders if not os.path.exists(root): os.makedirs(root, exist_ok=True) f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} network = pp.FractureNetwork3d([f_1], domain=domain) # mesh_args = {"mesh_size_bound": 1, "mesh_size_frac": 2, "mesh_size_min": 0.1} mesh_args = {"mesh_size_bound": 10, "mesh_size_frac": 10, "mesh_size_min": 10} file_name = str(root / 'test') gb = network.mesh(mesh_args=mesh_args, file_name=file_name) return network, file_name, gb
def test_three_intersecting_fractures(self, **kwargs): """ Three fractures intersecting, with intersecting intersections (point) """ f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-0.7, -0.7, 0.8, 0.8]]) ) f_3 = pp.Fracture(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1], [0, 0, 0, 0]])) # Add some parameters for grid size domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} mesh_args = {"mesh_size_frac": 0.5, "mesh_size_bound": 1, "mesh_size_min": 0.2} network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) network.mesh(mesh_args)
def create_gb_with_simple_fracture( path_head: str, ) -> Tuple[pp.FractureNetwork3d, Path, pp.GridBucket]: """ Setup method. Set up a fracture network and mesh it. Parameters ---------- path_head : str head of path to store test files Returns ------- network : pp.FractureNetwork3d file_name : Path path to the gmsh files with 'path/to/file_name', but without .geo/.msh endings gb : pp.GridBucket """ path = Path(__file__).resolve().parent / "results" root = path / path_head root.mkdir(parents=True, exist_ok=True) file_name = root / "gmsh_frac_file" f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } network = pp.FractureNetwork3d([f_1], domain=domain) # mesh_args = {"mesh_size_bound": 1, "mesh_size_frac": 2, "mesh_size_min": 0.1} mesh_args = { "mesh_size_bound": 10, "mesh_size_frac": 10, "mesh_size_min": 10 } gb = network.mesh(mesh_args=mesh_args, file_name=str(file_name)) return network, file_name, gb
def create_grid(self): """ Method that creates and returns the GridBucket of a 3D domain with two fractures. The two sides of the fractures are coupled together with a mortar grid. """ # define fractures f_1 = pp.EllipticFracture(np.array([-0.1, -0.3, -0.8]), 1.5, 1.5, np.pi / 6.3, np.pi / 2.2, np.pi / 4.1, num_points=8) f_2 = pp.EllipticFracture(np.array([1.5, 0.6, 0.8]), 1.5, 1.5, 0, np.pi / 2.3, -np.pi / 4.2, num_points=8) # Define a 3d FractureNetwork self.fractures = [f_1, f_2] network = pp.FractureNetwork3d([f_1, f_2], domain=self.domain) # Generate the mixed-dimensional mesh gb = network.mesh(self.mesh_args) # Remove fracture grid as it is not needed for g2 in gb.grids_of_dimension(2): gb.remove_node(g2) # Define the mortar grid meshing.create_mortar_grids(gb) g = gb.grids_of_dimension(3)[0] data_edge = gb.edge_props((g, g)) mg = data_edge['mortar_grid'] # Map the mortars to the subcell grid data_edge['mortar_grid_f2c'] = copy.deepcopy( mg) #keep copy of face to cell mortar meshing.map_mortar_to_submortar(gb) return gb
def test_two_intersecting_fractures(self, **kwargs): """ Two fractures intersecting along a line. The example also sets different characteristic mesh lengths on the boundary and at the fractures. """ f_1 = pp.Fracture(np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-0.7, -0.7, 0.8, 0.8]]) ) domain = {"xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2} mesh_args = {"mesh_size_frac": 0.5, "mesh_size_bound": 1, "mesh_size_min": 0.2} network = pp.FractureNetwork3d([f_1, f_2], domain=domain) network.mesh(mesh_args)
def test_two_intersecting_fractures(self, **kwargs): """ Two fractures intersecting along a line. The example also sets different characteristic mesh lengths on the boundary and at the fractures. """ f_1 = pp.Fracture( np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-0.7, -0.7, 0.8, 0.8]])) domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } mesh_args = { "mesh_size_frac": 0.5, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2], domain=domain) gb = network.mesh(mesh_args) isect_coord = np.array([[0, 0], [0, 0], [-0.7, 0.8]]) isect = IntersectionInfo(0, 1, isect_coord) self.check_gb( gb, domain, fractures=[f_1, f_2], isect_line=[isect], expected_num_1d_grids=1, )
def test_one_fracture_intersected_by_two(self, **kwargs): """ One fracture, intersected by two other (but no point intersections) """ f_1 = pp.Fracture( np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-0.7, -0.7, 0.8, 0.8]])) f_3 = pp.Fracture(f_2.p + np.array([0.5, 0, 0]).reshape((-1, 1))) # Add some parameters for grid size domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } mesh_args = { "mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) gb = network.mesh(mesh_args) isect_0_coord = np.array([[0, 0], [0, 0], [-0.7, 0.8]]) isect_1_coord = np.array([[0.5, 0.5], [0, 0], [-0.7, 0.8]]) isect_0 = IntersectionInfo(0, 1, isect_0_coord) isect_1 = IntersectionInfo(0, 2, isect_1_coord) self.check_gb( gb, domain, fractures=[f_1, f_2, f_3], isect_line=[isect_0, isect_1], expected_num_1d_grids=2, )
def test_split_into_octants(self, **kwargs): f_1 = pp.Fracture( np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[-1, -1, 1, 1], [-1, 1, 1, -1], [0, 0, 0, 0]])) f_3 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-1, -1, 1, 1]])) domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } mesh_args = { "mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) gb = network.mesh(mesh_args) isect_0_coord = np.array([[0, 0], [0, 0], [-1, 1]]) isect_1_coord = np.array([[-1, 1], [0, 0], [0, 0]]) isect_2_coord = np.array([[0, 0], [-1, 1], [0, 0]]) isect_0 = IntersectionInfo(0, 2, isect_0_coord) isect_1 = IntersectionInfo(0, 1, isect_1_coord) isect_2 = IntersectionInfo(1, 2, isect_2_coord) isect_pt = np.array([0, 0, 0]).reshape((-1, 1)) self.check_gb( gb, domain, fractures=[f_1, f_2, f_3], isect_line=[isect_0, isect_1, isect_2], isect_pt=[isect_pt], expected_num_1d_grids=6, expected_num_0d_grids=1, )
def test_two_fractures(self): # Test of method FractureNetwork.bounding_box() to inquire about # network extent f1 = pp.Fracture(np.array([[0, 2, 2, 0], [0, 0, 1, 1], [0, 0, 1, 1]]), check_convexity=False) f2 = pp.Fracture( np.array([[0, 1, 1, 0], [0, 0, 1, 1], [-1, -1, 1, 1]]), check_convexity=False, ) network = pp.FractureNetwork3d([f1, f2]) d = network.bounding_box() self.assertTrue(d["xmin"] == 0) self.assertTrue(d["xmax"] == 2) self.assertTrue(d["ymin"] == 0) self.assertTrue(d["ymax"] == 1) self.assertTrue(d["zmin"] == -1) self.assertTrue(d["zmax"] == 1)
def test_one_to_boundar_3d(self): """ One fracture in 3d going all the way to the boundary """ f_1 = np.array([[1, 5, 5, 1], [1, 1, 1, 1], [1, 1, 3, 3]]) f_set = [pp.Fracture(f_1)] domain = { "xmin": 0, "ymin": 0, "zmin": 0, "xmax": 5, "ymax": 5, "zmax": 5 } mesh_size_min = 0.1 mesh_size_frac = 0.1 mesh_size_bound = 2 on_boundary = np.array([ False, False, False, False, True, True, True, True, True, True, True, True ]) network = pp.FractureNetwork3d(f_set) network.impose_external_boundary(domain) network.find_intersections() network.split_intersections() network._insert_auxiliary_points( mesh_size_frac=mesh_size_frac, mesh_size_min=mesh_size_min, mesh_size_bound=mesh_size_bound, ) mesh_size = network._determine_mesh_size( boundary_point_tags=on_boundary) # 0.1 corresponds to fracture corners, 2.0 to domain corners far # away from the fracture and the other values to domain corners # affected by the mesh_size_known = np.array([ 0.1, 0.1, 0.1, 0.1, 2.0, 1.73205081, 2.0, 2.0, 2.0, 1.41421356, 2.0, 2.0 ]) self.assertTrue(np.all(np.isclose(mesh_size, mesh_size_known)))
def create_grid(self): """ Create a 3D grid with one fracture on a cube. The method assigns the following attributes to self: box (dict): Bounding box of the domain, defined by minimum and maximum values in each dimension. gb (pp.GridBucket): The produced grid bucket. Nd (int): Dimensions of the matrix. According to requirements by pp.models.ContactMechanics, the following method is called after gb is set: pp.contact_conditions.set_projections(self.gb) """ domain = { 'xmin': -2, 'xmax': 3, 'ymin': -2, 'ymax': 3, 'zmin': -3, 'zmax': 3 } self.box = domain # Fractures denoted by vertices f_1 = pp.Fracture(np.array([[0, 1, 2, 0], [0, 0, 1, 1], [0, 0, 1, 1]])) network = pp.FractureNetwork3d([f_1], domain=domain) mesh_args = { 'mesh_size_frac': 0.2, 'mesh_size_min': 0.2, 'mesh_size_bound': 1 } gb = network.mesh(mesh_args, ensure_matching_face_cell=False) self.gb = gb self.Nd = self.gb.dim_max pp.contact_conditions.set_projections(self.gb) print("Number of cells 3D grid ", self.gb.grids_of_dimension(3)[0].num_cells) breakpoint()
def test_three_fractures_sharing_line_same_segment(self, **kwargs): """ Three fractures that all share an intersection line. This can be considered as three intersection lines that coincide. """ f_1 = pp.Fracture( np.array([[-1, 1, 1, -1], [0, 0, 0, 0], [-1, -1, 1, 1]])) f_2 = pp.Fracture( np.array([[-1, 1, 1, -1], [-1, 1, 1, -1], [-1, -1, 1, 1]])) f_3 = pp.Fracture( np.array([[0, 0, 0, 0], [-1, 1, 1, -1], [-1, -1, 1, 1]])) domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } mesh_args = { "mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) gb = network.mesh(mesh_args) isect_coord = np.array([[0, 0], [0, 0], [-1, 1]]) isect = IntersectionInfo3Frac(0, 1, 2, isect_coord) self.check_gb( gb, domain, fractures=[f_1, f_2, f_3], isect_line=[isect], expected_num_1d_grids=1, expected_num_0d_grids=0, )
def test_T_intersection_is_partially_within_constraint(self, **kwargs): # a fracture f_1 = pp.Fracture(np.array([[0, 1, 1, 0], [0, 0, 1, 1], [0, 0, 0, 0]])) # a fracture that abuts the first fracture f_2 = pp.Fracture( np.array([[0.5, 0.5, 0.5, 0.5], [0.3, 1, 1, 0], [0, 0, 1, 1]])) # a fracture, to be constraint, that intersects in the same line f_3 = pp.Fracture( np.array([[0, 1, 1, 0], [0, 0, 1, 1], [-1, 1, 1, -1]])) domain = { "xmin": -2, "xmax": 2, "ymin": -2, "ymax": 2, "zmin": -2, "zmax": 2 } mesh_args = { "mesh_size_frac": 0.4, "mesh_size_bound": 1, "mesh_size_min": 0.2 } network = pp.FractureNetwork3d([f_1, f_2, f_3], domain=domain) gb = network.mesh(mesh_args, constraints=[2]) isect_coord = np.array([[0.5, 0.5], [0.3, 1], [0, 0]]) isect = IntersectionInfo(0, 1, isect_coord) self.check_gb( gb, domain, fractures=[f_1, f_2], isect_line=[isect], expected_num_1d_grids=1, expected_num_0d_grids=0, )
def import_grid(file_geo, tol): frac = pp.Fracture( np.array([[0, 10, 10, 0], [0, 0, 10, 10], [8, 2, 2, 8]]) * 10) network = pp.FractureNetwork3d([frac], tol=tol) domain = { "xmin": 0, "xmax": 100, "ymin": 0, "ymax": 100, "zmin": 0, "zmax": 100 } network.impose_external_boundary(domain) network.find_intersections() network.split_intersections() network.to_gmsh("dummy.geo") gb = pp.fracture_importer.dfm_from_gmsh(file_geo, 3, network) gb.compute_geometry() return gb, domain