Exemplo n.º 1
0
    def _generate_face_dofs(self, cell, degree, offset, variant, quad_deg):
        """Generate degrees of freedoms (dofs) for faces."""

        # Initialize empty dofs and identifiers (ids)
        dofs = []
        ids = dict(list(zip(list(range(4)), ([] for i in range(4)))))

        # Return empty info if not applicable
        d = cell.get_spatial_dimension()
        if (degree < 2):
            return (dofs, ids)

        msg = "2nd kind Nedelec face dofs only available with UFC convention"
        assert isinstance(cell, UFCTetrahedron), msg

        # Iterate over the faces of the tet
        num_faces = len(cell.get_topology()[2])
        for face in range(num_faces):

            # Construct quadrature scheme for this face
            m = 2 * (degree + 1)
            Q_face = UFCTetrahedronFaceQuadratureRule(face, m)

            # Construct Raviart-Thomas of (degree - 1) on the
            # reference face
            reference_face = Q_face.reference_rule().ref_el
            RT = RaviartThomas(reference_face, degree - 1, variant)
            num_rts = RT.space_dimension()

            # Evaluate RT basis functions at reference quadrature
            # points
            ref_quad_points = Q_face.reference_rule().get_points()
            num_quad_points = len(ref_quad_points)
            Phi = RT.get_nodal_basis()
            Phis = Phi.tabulate(ref_quad_points)[(0, 0)]

            # Note: Phis has dimensions:
            # num_basis_functions x num_components x num_quad_points

            # Map Phis -> phis (reference values to physical values)
            J = Q_face.jacobian()
            scale = 1.0 / numpy.sqrt(numpy.linalg.det(numpy.dot(J.T, J)))
            phis = numpy.ndarray((d, num_quad_points))
            for i in range(num_rts):
                for q in range(num_quad_points):
                    phi_i_q = scale * numpy.dot(J, Phis[numpy.newaxis, i, :, q].T)
                    for j in range(d):
                        phis[j, q] = phi_i_q[j]

                # Construct degrees of freedom as integral moments on
                # this cell, using the special face quadrature
                # weighted against the values of the (physical)
                # Raviart--Thomas'es on the face
                dofs += [IntegralMoment(cell, Q_face, phis)]

            # Assign identifiers (num RTs per face + previous edge dofs)
            ids[face] = list(range(offset + num_rts*face, offset + num_rts*(face + 1)))

        return (dofs, ids)
Exemplo n.º 2
0
    def _generate_face_dofs(self, cell, degree, offset):
        """Generate degrees of freedoms (dofs) for faces."""

        # Initialize empty dofs and identifiers (ids)
        dofs = []
        ids = dict(list(zip(list(range(4)), ([] for i in range(4)))))

        # Return empty info if not applicable
        d = cell.get_spatial_dimension()
        if (degree < 2):
            return (dofs, ids)

        msg = "2nd kind Nedelec face dofs only available with UFC convention"
        assert isinstance(cell, UFCTetrahedron), msg

        # Iterate over the faces of the tet
        num_faces = len(cell.get_topology()[2])
        for face in range(num_faces):

            # Construct quadrature scheme for this face
            m = 2 * (degree + 1)
            Q_face = UFCTetrahedronFaceQuadratureRule(face, m)

            # Construct Raviart-Thomas of (degree - 1) on the
            # reference face
            reference_face = Q_face.reference_rule().ref_el
            RT = RaviartThomas(reference_face, degree - 1)
            num_rts = RT.space_dimension()

            # Evaluate RT basis functions at reference quadrature
            # points
            ref_quad_points = Q_face.reference_rule().get_points()
            num_quad_points = len(ref_quad_points)
            Phi = RT.get_nodal_basis()
            Phis = Phi.tabulate(ref_quad_points)[(0, 0)]

            # Note: Phis has dimensions:
            # num_basis_functions x num_components x num_quad_points

            # Map Phis -> phis (reference values to physical values)
            J = Q_face.jacobian()
            scale = 1.0 / numpy.sqrt(numpy.linalg.det(numpy.dot(J.T, J)))
            phis = numpy.ndarray((d, num_quad_points))
            for i in range(num_rts):
                for q in range(num_quad_points):
                    phi_i_q = scale * numpy.dot(J, Phis[numpy.newaxis, i, :, q].T)
                    for j in range(d):
                        phis[j, q] = phi_i_q[j]

                # Construct degrees of freedom as integral moments on
                # this cell, using the special face quadrature
                # weighted against the values of the (physical)
                # Raviart--Thomas'es on the face
                dofs += [IntegralMoment(cell, Q_face, phis)]

            # Assign identifiers (num RTs per face + previous edge dofs)
            ids[face] = list(range(offset + num_rts*face, offset + num_rts*(face + 1)))

        return (dofs, ids)