Exemplo n.º 1
0
def triangle_grid_embedded(file_name):
    """Create triangular (2D) grid of a domain embedded in 3D space, without
    meshing the 3D volume.

    The resulting grid can be used in a DFN model. The grid will be fully
    conforming along intersections between fractures.

    This function produces a set of grids for fractures and lower-dimensional
    objects, but it does nothing to merge the grids. To create a GridBucket,
    use the function fracs.meshing.dfn instead, with the option
    conforming=True.

    To set the mesh size, use parameters mesh_size_frac and mesh_size_min, to represent the
    ideal and minimal mesh size sent to gmsh. For more details, see the gmsh
    manual on how to set mesh sizes.

    Parameters:
        file_name (str, optional): Filename for communication with gmsh.
            The config file for gmsh will be f_name.geo, with the grid output
            to f_name.msh. Defaults to dfn_network.

    Returns:
        list (length 3): For each dimension (2 -> 0), a list of all grids in
            that dimension.

    """

    if file_name[-4:] == ".geo" or file_name[-4:] == ".msh":
        file_name = file_name[:-4]

    out_file = file_name + ".msh"

    pts, cells, cell_info, phys_names = _read_gmsh_file(out_file)

    g_2d = mesh_2_grid.create_2d_grids(
        pts,
        cells,
        is_embedded=True,
        phys_names=phys_names,
        cell_info=cell_info,
    )
    g_1d, _ = mesh_2_grid.create_1d_grids(pts, cells, phys_names, cell_info)
    g_0d = mesh_2_grid.create_0d_grids(pts, cells, phys_names, cell_info)

    grids = [g_2d, g_1d, g_0d]

    logger.info("\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"
            logger.info(s)
    logger.info("\n")

    return grids
Exemplo n.º 2
0
def tetrahedral_grid_from_gmsh(file_name, constraints=None, **kwargs):
    """Generate a list of grids of dimensions {3, 2, 1, 0}, starting from a gmsh
    mesh.

    Parameters:
        file_name (str): Path to file of gmsh.msh specification.
        TODO: Line tag is unused. Maybe surface_tag replaces it?? Fix docs.
            This documentation is copied from mesh_2_grid.create_2d_grids().
        constraints (np.array, optional): Array with lists of lines that should not
            become grids. The array items should match the INDEX in line_tag, see above.

    Returns:
        list of list of grids: grids in 2d, 1d and 0d. If no grids exist in a
            specified dimension, the inner list will be empty.

    """

    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 = _read_gmsh_file(file_name)

    # 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,
        constraints=constraints,
    )

    g_1d, _ = mesh_2_grid.create_1d_grids(pts, cells, phys_names, cell_info)
    g_0d = mesh_2_grid.create_0d_grids(pts, cells, phys_names, cell_info)

    grids = [g_3d, g_2d, g_1d, g_0d]

    if verbose > 0:
        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
Exemplo n.º 3
0
def line_grid_from_gmsh(file_name, constraints=None, **kwargs):
    """Generate a list of grids dimensions {1, 0}, starting from a gmsh mesh.

    Parameters:
        file_name (str): Path to file of gmsh.msh specification.
        constraints (np.array, optional): Index of fracture lines that are
            constraints in the meshing, but should not have a lower-dimensional
            mesh. Defaults to empty.

    Returns:
        list of list of grids: grids in 2d, 1d and 0d. If no grids exist in a
            specified dimension, the inner list will be empty.

    """

    if constraints is None:
        constraints = np.empty(0, dtype=np.int)

    start_time = time.time()

    if file_name.endswith(".msh"):
        file_name = file_name[:-4]
    out_file = file_name + ".msh"

    pts, cells, cell_info, phys_names = _read_gmsh_file(out_file)

    # Constants used in the gmsh.geo-file
    const = constants.GmshConstants()

    # Create grids from gmsh mesh.
    logger.info("Create grids of various dimensions")
    g_1d, _ = mesh_2_grid.create_1d_grids(
        pts,
        cells,
        phys_names,
        cell_info,
        line_tag=const.PHYSICAL_NAME_FRACTURES,
        constraints=constraints,
        **kwargs,
    )
    g_0d = mesh_2_grid.create_0d_grids(pts, cells, phys_names, cell_info)
    grids = [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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
def triangle_grid_embedded(network,
                           find_isect=True,
                           f_name="dfn_network",
                           mesh_size_frac=None,
                           mesh_size_min=None,
                           mesh_size_bound=None,
                           **kwargs):
    """ Create triangular (2D) grid of a domain embedded in 3D space, without
    meshing the 3D volume.

    The resulting grid can be used in a DFN model. The grid will be fully
    conforming along intersections between fractures.

    This function produces a set of grids for fractures and lower-dimensional
    objects, but it does nothing to merge the grids. To create a GridBucket,
    use the function fracs.meshing.dfn instead, with the option
    conforming=True.

    To set the mesh size, use parameters mesh_size_frac and mesh_size_min, to represent the
    ideal and minimal mesh size sent to gmsh. For more details, see the gmsh
    manual on how to set mesh sizes.

    Parameters:
        network (FractureNetwork): To be meshed.
        find_isect (boolean, optional): If True (default), the network will
            search for intersections among fractures. Set False if
            network.find_intersections() already has been called.
        f_name (str, optional): Filename for communication with gmsh.
            The config file for gmsh will be f_name.geo, with the grid output
            to f_name.msh. Defaults to dfn_network.
        mesh_size_frac (double, optional): Target mesh size sent to gmsh. If not
            provided, gmsh will do its best to decide on the mesh size.
        mesh_size_min (double, optional): Minimal mesh size sent to gmsh. If not
            provided, gmsh will do its best to decide on the mesh size.
        **kwargs: Arguments sent to gmsh etc.

    Returns:
        list (length 3): For each dimension (2 -> 0), a list of all grids in
            that dimension.

    """

    verbose = 1

    if find_isect:
        network.find_intersections()

    # If fields mesh_size_frac and mesh_size_min are provided, try to estimate mesh sizes.
    if mesh_size_frac is not None and mesh_size_min is not None:
        if mesh_size_bound is None:
            mesh_size_bound = mesh_size_frac
        network.insert_auxiliary_points(mesh_size_frac, mesh_size_min,
                                        mesh_size_bound)
        # In this case we need to recompute intersection decomposition anyhow.
        network.split_intersections()

    if not hasattr(network, "decomposition"):
        network.split_intersections()
    else:
        logger.info("Use existing decomposition")

    pts, cells, cell_info, phys_names = _run_gmsh(f_name,
                                                  network,
                                                  in_3d=False,
                                                  **kwargs)
    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_2d, g_1d, g_0d]

    if verbose > 0:
        logger.info("\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"
                logger.info(s)
        logger.info("\n")

    return grids
Exemplo n.º 7
0
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
Exemplo n.º 8
0
def tetrahedral_grid_from_gmsh(network, file_name, **kwargs):
    """ Generate a list of grids of dimensions {3, 2, 1, 0}, starting from a gmsh
    mesh.

    Parameters:
        network (pp.FractureNetwork3d): The network used to generate the gmsh
            input file.
        file_name (str): Path to file of gmsh.msh specification.

    Returns:
        list of list of grids: grids in 2d, 1d and 0d. If no grids exist in a
            specified dimension, the inner list will be empty.

    """

    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"

    mesh = meshio.read(file_name)

    pts = mesh.points
    cells = mesh.cells
    cell_info = mesh.cell_data
    # Invert phys_names dictionary to map from physical tags to corresponding
    # physical names
    phys_names = {v[0]: k for k, v in mesh.field_data.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:
        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
Exemplo n.º 9
0
def triangle_grid_embedded(network, f_name, **kwargs):
    """ Create triangular (2D) grid of a domain embedded in 3D space, without
    meshing the 3D volume.

    The resulting grid can be used in a DFN model. The grid will be fully
    conforming along intersections between fractures.

    This function produces a set of grids for fractures and lower-dimensional
    objects, but it does nothing to merge the grids. To create a GridBucket,
    use the function fracs.meshing.dfn instead, with the option
    conforming=True.

    To set the mesh size, use parameters mesh_size_frac and mesh_size_min, to represent the
    ideal and minimal mesh size sent to gmsh. For more details, see the gmsh
    manual on how to set mesh sizes.

    Parameters:
        network (FractureNetwork): To be meshed.
        f_name (str, optional): Filename for communication with gmsh.
            The config file for gmsh will be f_name.geo, with the grid output
            to f_name.msh. Defaults to dfn_network.
        **kwargs: Arguments sent to gmsh etc.

    Returns:
        list (length 3): For each dimension (2 -> 0), a list of all grids in
            that dimension.

    """

    out_file = _run_gmsh(f_name, in_3d=False, **kwargs)

    # The interface of meshio changed between versions 1 and 2. We make no
    # assumption on which version is installed here.
    if int(meshio.__version__[0]) < 2:
        pts, cells, _, cell_info, phys_names = meshio.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()}
    else:
        mesh = meshio.read(out_file)

        pts = mesh.points
        cells = mesh.cells
        cell_info = mesh.cell_data
        phys_names = {v[0]: k for k, v in mesh.field_data.items()}

    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_2d, g_1d, g_0d]

    logger.info("\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"
            logger.info(s)
    logger.info("\n")

    return grids