def _run_gmsh(file_name, network, **kwargs): verbose = kwargs.get("verbose", 1) if file_name[-4:] == ".geo" or file_name[-4:] == ".msh": file_name = file_name[:-4] in_file = file_name + ".geo" out_file = file_name + ".msh" if not hasattr(network, "decomposition"): network.split_intersections() else: logger.info("Use existing decomposition") network.to_gmsh(in_file, **kwargs) gmsh_opts = kwargs.get("gmsh_opts", {}) gmsh_verbose = kwargs.get("gmsh_verbose", verbose) gmsh_opts["-v"] = gmsh_verbose gmsh_status = gmsh_interface.run_gmsh(in_file, out_file, dims=3, **gmsh_opts) if verbose > 0: if gmsh_status == 0: logger.info("Gmsh processed file successfully") else: logger.error("Gmsh failed with status " + str(gmsh_status)) sys.exit() pts, cells, _, cell_info, phys_names = gmsh_io.read(out_file) # Invert phys_names dictionary to map from physical tags to corresponding # physical names phys_names = {v[0]: k for k, v in phys_names.items()} return pts, cells, cell_info, phys_names
def tetrahedral_grid_from_gmsh(file_name, network, **kwargs): start_time = time.time() # Verbosity level verbose = kwargs.get("verbose", 1) if file_name.endswith(".msh"): file_name = file_name[:-4] file_name = file_name + ".msh" pts, cells, _, cell_info, phys_names = gmsh_io.read(file_name) # Invert phys_names dictionary to map from physical tags to corresponding # physical names phys_names = {v[0]: k for k, v in phys_names.items()} # Call upon helper functions to create grids in various dimensions. # The constructors require somewhat different information, reflecting the # different nature of the grids. g_3d = mesh_2_grid.create_3d_grids(pts, cells) g_2d = mesh_2_grid.create_2d_grids( pts, cells, is_embedded=True, phys_names=phys_names, cell_info=cell_info, network=network, ) g_1d, _ = mesh_2_grid.create_1d_grids(pts, cells, phys_names, cell_info) g_0d = mesh_2_grid.create_0d_grids(pts, cells) grids = [g_3d, g_2d, g_1d, g_0d] if verbose > 0: print("\n") print("Grid creation completed. Elapsed time " + str(time.time() - start_time)) print("\n") 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" print(s) print("\n") return grids
def triangle_grid_from_gmsh(file_name, **kwargs): start_time = time.time() if file_name.endswith(".msh"): file_name = file_name[:-4] out_file = file_name + ".msh" # Verbosity level verbose = kwargs.get("verbose", 1) pts, cells, _, cell_info, phys_names = gmsh_io.read(out_file) # Invert phys_names dictionary to map from physical tags to corresponding # physical names. # As of meshio 1.10, the value of the physical name is defined as a numpy # array, with the first item being the tag, the second the dimension. phys_names = {v[0]: k for k, v in phys_names.items()} # Constants used in the gmsh.geo-file const = constants.GmshConstants() # Create grids from gmsh mesh. logger.info("Create grids of various dimensions") g_2d = mesh_2_grid.create_2d_grids(pts, cells, is_embedded=False) g_1d, _ = mesh_2_grid.create_1d_grids( pts, cells, phys_names, cell_info, line_tag=const.PHYSICAL_NAME_FRACTURES ) g_0d = mesh_2_grid.create_0d_grids(pts, cells) grids = [g_2d, g_1d, g_0d] logger.info( "Grid creation completed. Elapsed time " + str(time.time() - start_time) ) 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 grids
def _run_gmsh(file_name, network, **kwargs): verbose = kwargs.get('verbose', 1) if file_name[-4:] == '.geo' or file_name[-4:] == '.msh': file_name = file_name[:-4] in_file = file_name + '.geo' out_file = file_name + '.msh' if not hasattr(network, 'decomposition'): network.split_intersections() else: print('Use existing decomposition') network.to_gmsh(in_file, **kwargs) gmsh_opts = kwargs.get('gmsh_opts', {}) gmsh_verbose = kwargs.get('gmsh_verbose', verbose) gmsh_opts['-v'] = gmsh_verbose gmsh_status = gmsh_interface.run_gmsh(in_file, out_file, dims=3, **gmsh_opts) if verbose > 0: if gmsh_status == 0: print('Gmsh processed file successfully') else: print('Gmsh failed with status ' + str(gmsh_status)) sys.exit() pts, cells, _, cell_info, phys_names = gmsh_io.read(out_file) # Invert phys_names dictionary to map from physical tags to corresponding # physical names phys_names = {v[0]: k for k, v in phys_names.items()} return pts, cells, cell_info, phys_names
def tetrahedral_grid(fracs=None, box=None, network=None, subdomains=[], **kwargs): """ Create grids for a domain with possibly intersecting fractures in 3d. The function can be call through the wrapper function meshing.simplex_grid. Based on the specified fractures, the method computes fracture intersections if necessary, creates a gmsh input file, runs gmsh and reads the result, and then constructs grids in 3d (the whole domain), 2d (one for each individual fracture), 1d (along fracture intersections), and 0d (meeting between intersections). The fractures can be specified is terms of the keyword 'fracs' (either as numpy arrays or Fractures, see below), or as a ready-made FractureNetwork by the keyword 'network'. For fracs, the boundary of the domain must be specified as well, by 'box'. For a ready network, the boundary will be imposed if provided. For a network will use pre-computed intersection and decomposition if these are available (attributes 'intersections' and 'decomposition'). Parameters ---------- fracs (list, optional): List of either pre-defined fractures, or np.ndarrays, (each 3xn) of fracture vertexes. box (dictionary, optional). Domain specification. Should have keywords xmin, xmax, ymin, ymax, zmin, zmax. network (fractures.FractureNetwork, optional): A FractureNetwork containing fractures. subdomain (list, optional): List of planes partitioning the 3d domain into subdomains. The planes are defined in the same way as fracs. The fractures should be specified either by a combination of fracs and box, or by network (possibly combined with box). See above. **kwargs: To be explored. Returns ------- list (length 4): For each dimension (3 -> 0), a list of all grids in that dimension. Examples -------- frac1 = np.array([[1,1,4,4], [1,4,4,1], [2,2,2,2]]) frac2 = np.array([[2,2,2,2], [1,1,4,4], [1,4,4,1]]) fracs = [frac1, frac2] domain = {'xmin': 0, 'ymin': 0, 'zmin': 0, 'xmax': 5, 'ymax': 5, 'zmax': 5,} path_to_gmsh = .... # Set the sytem path to gmsh gb = tetrahedral_grid(fracs, domain, gmsh_path = path_to_gmsh) """ # Verbosity level verbose = kwargs.get('verbose', 1) # File name for communication with gmsh file_name = kwargs.pop('file_name', 'gmsh_frac_file') if network is None: frac_list = [] for f in fracs: # Input can be either numpy arrays or predifined fractures. As a # guide, we treat f as a fracture if it has an attribute p which is # a numpy array. # If f turns out not to be a fracture, strange errors will result # as the further program tries to access non-existing methods. # The correct treatment here would be several # isinstance-statements, but that became less than elegant. To # revisit. if hasattr(f, 'p') and isinstance(f.p, np.ndarray): frac_list.append(f) else: # Convert the fractures from numpy representation to our 3D # fracture data structure. frac_list.append(fractures.Fracture(f)) # Combine the fractures into a network network = fractures.FractureNetwork(frac_list, verbose=verbose, tol=kwargs.get('tol', 1e-4)) # Add any subdomain boundaries: network.add_subdomain_boundaries(subdomains) # Impose external boundary. If box is None, a domain size somewhat larger # than the network will be assigned. network.impose_external_boundary(box) # Find intersections and split them, preparing the way for dumping the # network to gmsh if not network.has_checked_intersections: network.find_intersections() else: print('Use existing intersections') start_time = time.time() # If fields h_ideal and h_min are provided, try to estimate mesh sizes. h_ideal = kwargs.get('h_ideal', None) h_min = kwargs.get('h_min', None) if h_ideal is not None and h_min is not None: network.insert_auxiliary_points(h_ideal, h_min) # In this case we need to recompute intersection decomposition anyhow. network.split_intersections() if not hasattr(network, 'decomposition'): network.split_intersections() else: print('Use existing decomposition') in_file = file_name + '.geo' out_file = file_name + '.msh' network.to_gmsh(in_file, **kwargs) gmsh_opts = kwargs.get('gmsh_opts', {}) gmsh_verbose = kwargs.get('gmsh_verbose', verbose) gmsh_opts['-v'] = gmsh_verbose gmsh_status = gmsh_interface.run_gmsh(in_file, out_file, dims=3, **gmsh_opts) if verbose > 0: start_time = time.time() if gmsh_status == 0: print('Gmsh processed file successfully') else: print('Gmsh failed with status ' + str(gmsh_status)) pts, cells, _, cell_info, phys_names = gmsh_io.read(out_file) # Invert phys_names dictionary to map from physical tags to corresponding # physical names phys_names = {v[0]: k for k, v in phys_names.items()} # Call upon helper functions to create grids in various dimensions. # The constructors require somewhat different information, reflecting the # different nature of the grids. g_3d = mesh_2_grid.create_3d_grids(pts, cells) g_2d = mesh_2_grid.create_2d_grids(pts, cells, is_embedded=True, phys_names=phys_names, cell_info=cell_info, network=network) g_1d, _ = mesh_2_grid.create_1d_grids(pts, cells, phys_names, cell_info) g_0d = mesh_2_grid.create_0d_grids(pts, cells) grids = [g_3d, g_2d, g_1d, g_0d] if verbose > 0: print('\n') print('Grid creation completed. Elapsed time ' + str(time.time() - start_time)) print('\n') 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' print(s) print('\n') return grids