Example #1
0
def test_nodal_enriched_implementation():
    """Following element pair should be the same.
    This might be fragile to dof reordering but works now.
    """

    e0 = RaviartThomas(T, 2)

    e1 = NodalEnrichedElement(
        RestrictedElement(RaviartThomas(T, 2), restriction_domain='facet'),
        RestrictedElement(RaviartThomas(T, 2), restriction_domain='interior'))

    for attr in [
            "degree",
            "get_reference_element",
            "entity_dofs",
            "entity_closure_dofs",
            "get_formdegree",
            "mapping",
            "num_sub_elements",
            "space_dimension",
            "value_shape",
            "is_nodal",
    ]:
        assert getattr(e0, attr)() == getattr(e1, attr)()
    assert np.allclose(e0.get_coeffs(), e1.get_coeffs())
    assert np.allclose(e0.dmats(), e1.dmats())
    assert np.allclose(e0.get_dual_set().to_riesz(e0.get_nodal_basis()),
                       e1.get_dual_set().to_riesz(e1.get_nodal_basis()))
Example #2
0
    def _generate_cell_dofs(self, cell, degree, offset, variant, quad_deg):
        """Generate degrees of freedoms (dofs) for entities of
        codimension d (cells)."""

        # Return empty info if not applicable
        d = cell.get_spatial_dimension()
        if (d == 2 and degree < 2) or (d == 3 and degree < 3):
            return ([], {0: []})

        # Create quadrature points
        Q = make_quadrature(cell, 2 * (degree + 1))
        qs = Q.get_points()

        # Create Raviart-Thomas nodal basis
        RT = RaviartThomas(cell, degree + 1 - d, variant)
        phi = RT.get_nodal_basis()

        # Evaluate Raviart-Thomas basis at quadrature points
        phi_at_qs = phi.tabulate(qs)[(0,) * d]

        # Use (Frobenius) integral moments against RTs as dofs
        dofs = [IntegralMoment(cell, Q, phi_at_qs[i, :])
                for i in range(len(phi_at_qs))]

        # Associate these dofs with the interior
        ids = {0: list(range(offset, offset + len(dofs)))}
        return (dofs, ids)
    def _generate_cell_dofs(self, cell, degree, offset):
        """Generate degrees of freedoms (dofs) for entities of
        codimension d (cells)."""

        # Return empty info if not applicable
        d = cell.get_spatial_dimension()
        if (d == 2 and degree < 2) or (d == 3 and degree < 3):
            return ([], {0: []})

        # Create quadrature points
        Q = make_quadrature(cell, 2 * (degree + 1))
        qs = Q.get_points()

        # Create Raviart-Thomas nodal basis
        RT = RaviartThomas(cell, degree + 1 - d)
        phi = RT.get_nodal_basis()

        # Evaluate Raviart-Thomas basis at quadrature points
        phi_at_qs = phi.tabulate(qs)[(0,) * d]

        # Use (Frobenius) integral moments against RTs as dofs
        dofs = [IntegralMoment(cell, Q, phi_at_qs[i, :])
                for i in range(len(phi_at_qs))]

        # Associate these dofs with the interior
        ids = {0: list(range(offset, offset + len(dofs)))}
        return (dofs, ids)
Example #4
0
def test_nodal_enriched_implementation():
    """Following element pair should be the same.
    This might be fragile to dof reordering but works now.
    """

    e0 = RaviartThomas(T, 2)

    e1 = NodalEnrichedElement(
        RestrictedElement(RaviartThomas(T, 2), restriction_domain='facet'),
        RestrictedElement(RaviartThomas(T, 2), restriction_domain='interior')
    )

    for attr in ["degree",
                 "get_reference_element",
                 "entity_dofs",
                 "entity_closure_dofs",
                 "get_formdegree",
                 "mapping",
                 "num_sub_elements",
                 "space_dimension",
                 "value_shape",
                 "is_nodal",
                 ]:
        assert getattr(e0, attr)() == getattr(e1, attr)()
    assert np.allclose(e0.get_coeffs(), e1.get_coeffs())
    assert np.allclose(e0.dmats(), e1.dmats())
    assert np.allclose(e0.get_dual_set().to_riesz(e0.get_nodal_basis()),
                       e1.get_dual_set().to_riesz(e1.get_nodal_basis()))
Example #5
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)
    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)