Esempio n. 1
0
    def _generate_dofs(cell, entity_dim, degree, offset):
        """generate degrees of freedom for enetities of dimension entity_dim

        Input: all obvious except
           offset  -- the current first available dof id.

        Output:
           dofs    -- an array of dofs associated to entities in that dim
           dof_ids -- a dict mapping entity_id to the range of indices of dofs
                      associated to it.

        On a k-face for degree r, the dofs are given by the value of
           t^T u t
        evaluated at points enough to control P(r-k+1) for all the edge
        tangents of the face.
        `cell.make_points(entity_dim, entity_id, degree + 2)` happens to
        generate exactly those points needed.
        """
        dofs = []
        dof_ids = {}
        num_entities = len(cell.get_topology()[entity_dim])
        for entity_id in range(num_entities):
            pts = cell.make_points(entity_dim, entity_id, degree + 2)
            tangents = cell.compute_face_edge_tangents(entity_dim, entity_id)
            dofs += [
                InnerProduct(cell, t, t, pt) for pt in pts for t in tangents
            ]
            num_new_dofs = len(pts) * len(tangents)
            dof_ids[entity_id] = list(range(offset, offset + num_new_dofs))
            offset += num_new_dofs
        return (dofs, dof_ids)
Esempio n. 2
0
 def _generate_edge_dofs(cell, degree, offset):
     """Generate dofs on edges.
     On each edge, let n be its normal. For degree=r, the scalar function
           n^T u n
     is evaluated at points enough to control P(r).
     """
     dofs = []
     dof_ids = {}
     for entity_id in range(3):  # a triangle has 3 edges
         pts = cell.make_points(1, entity_id, degree + 2)  # edges are 1D
         normal = cell.compute_scaled_normal(entity_id)
         dofs += [InnerProduct(cell, normal, normal, pt) for pt in pts]
         num_new_dofs = len(pts)  # 1 dof per point on edge
         dof_ids[entity_id] = list(range(offset, offset + num_new_dofs))
         offset += num_new_dofs
     return (dofs, dof_ids)
Esempio n. 3
0
 def _generate_trig_dofs(cell, degree, offset):
     """Generate dofs on edges.
     On each triangle, for degree=r, the three components
           u11, u12, u22
     are evaluated at points enough to control P(r-1).
     """
     dofs = []
     dof_ids = {}
     pts = cell.make_points(2, 0, degree + 2)  # 2D trig #0
     e1 = np.array([1.0, 0.0])  # euclidean basis 1
     e2 = np.array([0.0, 1.0])  # euclidean basis 2
     basis = [(e1, e1), (e1, e2), (e2, e2)]  # basis for symmetric matrix
     for (v1, v2) in basis:
         dofs += [InnerProduct(cell, v1, v2, pt) for pt in pts]
     num_dofs = 3 * len(pts)  # 3 dofs per trig
     dof_ids[0] = list(range(offset, offset + num_dofs))
     return (dofs, dof_ids)
Esempio n. 4
0
    def __init__(self, cell, degree):
        if not degree == 3:
            raise ValueError("Arnold-Winther elements are"
                             "only defined for degree 3.")
        dofs = []
        dof_ids = {}
        dof_ids[0] = {0: [], 1: [], 2: []}
        dof_ids[1] = {0: [], 1: [], 2: []}
        dof_ids[2] = {0: []}

        dof_cur = 0

        # vertex dofs
        vs = cell.get_vertices()
        e1 = numpy.array([1.0, 0.0])
        e2 = numpy.array([0.0, 1.0])
        basis = [(e1, e1), (e1, e2), (e2, e2)]

        dof_cur = 0

        for entity_id in range(3):
            node = tuple(vs[entity_id])
            for (v1, v2) in basis:
                dofs.append(InnerProduct(cell, v1, v2, node))
            dof_ids[0][entity_id] = list(range(dof_cur, dof_cur + 3))
            dof_cur += 3

        # edge dofs now
        # moments of normal . sigma against constants and linears.
        for entity_id in range(3):
            for order in (0, 1):
                dofs += [
                    IntegralLegendreNormalNormalMoment(cell, entity_id, order,
                                                       6),
                    IntegralLegendreNormalTangentialMoment(
                        cell, entity_id, order, 6)
                ]
            dof_ids[1][entity_id] = list(range(dof_cur, dof_cur + 4))
            dof_cur += 4

        # internal dofs: constant moments of three unique components
        Q = make_quadrature(cell, 3)

        e1 = numpy.array([1.0, 0.0])  # euclidean basis 1
        e2 = numpy.array([0.0, 1.0])  # euclidean basis 2
        basis = [(e1, e1), (e1, e2), (e2, e2)]  # basis for symmetric matrices
        for (v1, v2) in basis:
            v1v2t = numpy.outer(v1, v2)
            fatqp = numpy.zeros((2, 2, len(Q.pts)))
            for k in range(len(Q.pts)):
                fatqp[:, :, k] = v1v2t
            dofs.append(FIM(cell, Q, fatqp))
        dof_ids[2][0] = list(range(dof_cur, dof_cur + 3))
        dof_cur += 3

        # Constraint dofs

        Q = make_quadrature(cell, 5)

        onp = ONPolynomialSet(cell, 2, (2, ))
        pts = Q.get_points()
        onpvals = onp.tabulate(pts)[0, 0]

        for i in list(range(3, 6)) + list(range(9, 12)):
            dofs.append(
                IntegralMomentOfTensorDivergence(cell, Q, onpvals[i, :, :]))

        dof_ids[2][0] += list(range(dof_cur, dof_cur + 6))

        super(ArnoldWintherDual, self).__init__(dofs, cell, dof_ids)