Exemple #1
0
 def create_1d_from_nodes(nodes):
     # From a set of nodes, create a 1d grid. duplicate nodes are removed
     # and we verify that the nodes are indeed colinear
     assert cg.is_collinear(nodes, tol=tol)
     sort_ind = cg.argsort_point_on_line(nodes, tol=tol)
     n = nodes[:, sort_ind]
     unique_nodes, _, _ = unique_columns_tol(n, tol=tol)
     g = TensorGrid(np.arange(unique_nodes.shape[1]))
     g.nodes = unique_nodes
     g.compute_geometry()
     return g, sort_ind
Exemple #2
0
def create_embedded_line_grid(loc_coord, glob_id, tol=1e-4):
    loc_center = np.mean(loc_coord, axis=1).reshape((-1, 1))
    loc_coord -= loc_center
    # Check that the points indeed form a line
    if not cg.is_collinear(loc_coord, tol):
        raise ValueError("Elements are not colinear")
    # Find the tangent of the line
    tangent = cg.compute_tangent(loc_coord)
    # Projection matrix
    rot = cg.project_line_matrix(loc_coord, tangent)

    loc_coord_1d = rot.dot(loc_coord)
    # The points are now 1d along one of the coordinate axis, but we
    # don't know which yet. Find this.

    sum_coord = np.sum(np.abs(loc_coord_1d), axis=1)
    sum_coord /= np.amax(sum_coord)
    active_dimension = np.logical_not(
        np.isclose(sum_coord, 0, atol=tol, rtol=0))
    # Check that we are indeed in 1d
    assert np.sum(active_dimension) == 1
    # Sort nodes, and create grid
    coord_1d = loc_coord_1d[active_dimension]
    sort_ind = np.argsort(coord_1d)[0]
    sorted_coord = coord_1d[0, sort_ind]
    g = structured.TensorGrid(sorted_coord)

    # Project back to active dimension
    nodes = np.zeros(g.nodes.shape)
    nodes[active_dimension] = g.nodes[0]
    g.nodes = nodes

    # Project back again to 3d coordinates

    irot = rot.transpose()
    g.nodes = irot.dot(g.nodes)
    g.nodes += loc_center

    # Add mapping to global point numbers
    g.global_point_ind = glob_id[sort_ind]
    return g
Exemple #3
0
def grid(g):
    """ Sanity check for the grid. General method which apply the following:
    - check if the face normals are actually normal to the faces
    - check if a bidimensional grid is planar

    Args:
        g (grid): Grid, or a subclass, with geometry fields computed.

    How to use:
        import core.grids.check as check
        check.grid(g)
    """

    if g.dim == 1:
        assert cg.is_collinear(g.nodes)
        face_normals_1d(g)

    if g.dim == 2:
        assert cg.is_planar(g.nodes)

    if g.dim != 1:
        face_normals(g)
Exemple #4
0
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)