Ejemplo n.º 1
0
def face_normals(g):
    """ Check if the face normals are actually normal to the faces.

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

    nodes, faces, _ = sps.find(g.face_nodes)

    for f in np.arange(g.num_faces):
        loc = slice(g.face_nodes.indptr[f], g.face_nodes.indptr[f + 1])
        normal = g.face_normals[:, f]
        tangent = cg.compute_tangent(g.nodes[:, nodes[loc]])
        assert np.isclose(np.dot(normal, tangent), 0)
Ejemplo n.º 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
Ejemplo n.º 3
0
    def __compute_geometry_1d(self):
        "Compute 1D geometry"

        self.face_areas = np.ones(self.num_faces)

        fn = self.face_nodes.indices
        n = fn.size
        self.face_centers = self.nodes[:, fn]

        self.face_normals = np.tile(cg.compute_tangent(self.nodes), (n, 1)).T

        cf = self.cell_faces.indices
        xf1 = self.face_centers[:, cf[::2]]
        xf2 = self.face_centers[:, cf[1::2]]

        self.cell_volumes = np.linalg.norm(xf1 - xf2, axis=0)
        self.cell_centers = 0.5 * (xf1 + xf2)

        # Ensure that normal vector direction corresponds with sign convention
        # in self.cellFaces
        def nrm(u):
            return np.sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2])

        [fi, ci, val] = sps.find(self.cell_faces)
        _, idx = np.unique(fi, return_index=True)
        sgn = val[idx]
        fc = self.face_centers[:, fi[idx]]
        cc = self.cell_centers[:, ci[idx]]
        v = fc - cc
        # Prolong the vector from cell to face center in the direction of the
        # normal vector. If the prolonged vector is shorter, the normal should
        # flipped
        vn = v + nrm(v) * self.face_normals[:, fi[idx]] * 0.001
        flip = np.logical_or(
            np.logical_and(nrm(v) > nrm(vn), sgn > 0),
            np.logical_and(nrm(v) < nrm(vn), sgn < 0),
        )
        self.face_normals[:, flip] *= -1