Esempio n. 1
0
    def __init__(self, ref_el, degree):
        nodes = []
        dim = ref_el.get_spatial_dimension()

        Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1))

        f_at_qpts = numpy.ones(len(Q.wts))
        nodes.append(functional.IntegralMoment(ref_el, Q, f_at_qpts))

        vertices = ref_el.get_vertices()
        midpoint = tuple(sum(numpy.array(vertices)) / len(vertices))
        for k in range(1, degree + 1):
            # Loop over all multi-indices of degree k.
            for alpha in mis(dim, k):
                nodes.append(
                    functional.PointDerivative(ref_el, midpoint, alpha))

        entity_ids = {
            d: {e: []
                for e in ref_el.sub_entities[d]}
            for d in range(dim + 1)
        }
        entity_ids[dim][0] = list(range(len(nodes)))

        super(DiscontinuousTaylorDualSet,
              self).__init__(nodes, ref_el, entity_ids)
Esempio n. 2
0
    def __init__(self, ref_el, degree):
        sd = ref_el.get_spatial_dimension()
        if sd != 2:
            raise Exception("Nedelec2D only works on triangles")

        nodes = []

        t = ref_el.get_topology()

        num_edges = len(t[1])

        # edge tangents
        for i in range(num_edges):
            pts_cur = ref_el.make_points(1, i, degree + 2)
            for j in range(len(pts_cur)):
                pt_cur = pts_cur[j]
                f = functional.PointEdgeTangentEvaluation(ref_el, i, pt_cur)
                nodes.append(f)

        # internal moments
        if degree > 0:
            Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1))
            qpts = Q.get_points()
            Pkm1 = polynomial_set.ONPolynomialSet(ref_el, degree - 1)
            zero_index = tuple([0 for i in range(sd)])
            Pkm1_at_qpts = Pkm1.tabulate(qpts)[zero_index]

            for d in range(sd):
                for i in range(Pkm1_at_qpts.shape[0]):
                    phi_cur = Pkm1_at_qpts[i, :]
                    l_cur = functional.IntegralMoment(ref_el, Q, phi_cur,
                                                      (d, ))
                    nodes.append(l_cur)

        entity_ids = {}

        # set to empty
        for i in range(sd + 1):
            entity_ids[i] = {}
            for j in range(len(t[i])):
                entity_ids[i][j] = []

        cur = 0

        # edges
        num_edge_pts = len(ref_el.make_points(1, 0, degree + 2))

        for i in range(len(t[1])):
            entity_ids[1][i] = list(range(cur, cur + num_edge_pts))
            cur += num_edge_pts

        # moments against P_{degree-1} internally, if degree > 0
        if degree > 0:
            num_internal_dof = sd * Pkm1_at_qpts.shape[0]
            entity_ids[2][0] = list(range(cur, cur + num_internal_dof))

        super(NedelecDual2D, self).__init__(nodes, ref_el, entity_ids)
Esempio n. 3
0
    def __init__(self, ref_el, degree, order=1):
        bc_nodes = []
        for x in ref_el.get_vertices():
            bc_nodes.append([functional.PointEvaluation(ref_el, x),
                             *[functional.PointDerivative(ref_el, x, [alpha]) for alpha in range(1, order)]])
        bc_nodes[1].reverse()
        k = len(bc_nodes[0])
        idof = slice(k, -k)
        bdof = list(range(-k, k))
        bdof = bdof[k:] + bdof[:k]

        # Define the generalized eigenproblem on a GLL element
        gll = GaussLobattoLegendre(ref_el, degree)
        xhat = numpy.array([list(x.get_point_dict().keys())[0][0] for x in gll.dual_basis()])

        # Tabulate the BC nodes
        constraints = gll.tabulate(order-1, ref_el.get_vertices())
        C = numpy.column_stack(list(constraints.values()))
        perm = list(range(len(bdof)))
        perm = perm[::2] + perm[-1::-2]
        C = C[:, perm].T

        # Tabulate the basis that splits the DOFs into interior and bcs
        E = numpy.eye(gll.space_dimension())
        E[bdof, idof] = -C[:, idof]
        E[bdof, :] = numpy.dot(numpy.linalg.inv(C[:, bdof]), E[bdof, :])

        # Assemble the constrained Galerkin matrices on the reference cell
        rule = quadrature.GaussLegendreQuadratureLineRule(ref_el, degree+1)
        phi = gll.tabulate(order, rule.get_points())
        E0 = numpy.dot(phi[(0, )].T, E)
        Ek = numpy.dot(phi[(order, )].T, E)
        B = numpy.dot(numpy.multiply(E0.T, rule.get_weights()), E0)
        A = numpy.dot(numpy.multiply(Ek.T, rule.get_weights()), Ek)

        # Eigenfunctions in the constrained basis
        S = numpy.eye(A.shape[0])
        if S.shape[0] > len(bdof):
            _, Sii = sym_eig(A[idof, idof], B[idof, idof])
            S[idof, idof] = Sii
            S[idof, bdof] = numpy.dot(Sii, numpy.dot(Sii.T, -B[idof, bdof]))

        # Eigenfunctions in the Lagrange basis
        S = numpy.dot(E, S)
        self.gll_points = xhat
        self.gll_tabulation = S.T

        # Interpolate eigenfunctions onto the quadrature points
        basis = numpy.dot(S.T, phi[(0, )])
        nodes = bc_nodes[0] + [functional.IntegralMoment(ref_el, rule, f) for f in basis[idof]] + bc_nodes[1]

        entity_ids = {0: {0: [0], 1: [degree]},
                      1: {0: list(range(1, degree))}}
        entity_permutations = {}
        entity_permutations[0] = {0: {0: [0]}, 1: {0: [0]}}
        entity_permutations[1] = {0: make_entity_permutations(1, degree - 1)}
        super(FDMDual, self).__init__(nodes, ref_el, entity_ids, entity_permutations)
Esempio n. 4
0
    def __init__(self, ref_el, degree, variant, quad_deg):
        entity_ids = {}
        nodes = []

        sd = ref_el.get_spatial_dimension()
        t = ref_el.get_topology()

        if variant == "integral":
            facet = ref_el.get_facet_element()
            # Facet nodes are \int_F v\cdot n p ds where p \in P_{q-1}
            # degree is q - 1
            Q = quadrature.make_quadrature(facet, quad_deg)
            Pq = polynomial_set.ONPolynomialSet(facet, degree)
            Pq_at_qpts = Pq.tabulate(Q.get_points())[tuple([0] * (sd - 1))]
            for f in range(len(t[sd - 1])):
                for i in range(Pq_at_qpts.shape[0]):
                    phi = Pq_at_qpts[i, :]
                    nodes.append(
                        functional.IntegralMomentOfScaledNormalEvaluation(
                            ref_el, Q, phi, f))

            # internal nodes. These are \int_T v \cdot p dx where p \in P_{q-2}^d
            if degree > 0:
                Q = quadrature.make_quadrature(ref_el, quad_deg)
                qpts = Q.get_points()
                Pkm1 = polynomial_set.ONPolynomialSet(ref_el, degree - 1)
                zero_index = tuple([0 for i in range(sd)])
                Pkm1_at_qpts = Pkm1.tabulate(qpts)[zero_index]

                for d in range(sd):
                    for i in range(Pkm1_at_qpts.shape[0]):
                        phi_cur = Pkm1_at_qpts[i, :]
                        l_cur = functional.IntegralMoment(
                            ref_el, Q, phi_cur, (d, ), (sd, ))
                        nodes.append(l_cur)

        elif variant == "point":
            # codimension 1 facets
            for i in range(len(t[sd - 1])):
                pts_cur = ref_el.make_points(sd - 1, i, sd + degree)
                for j in range(len(pts_cur)):
                    pt_cur = pts_cur[j]
                    f = functional.PointScaledNormalEvaluation(
                        ref_el, i, pt_cur)
                    nodes.append(f)

            # internal nodes.  Let's just use points at a lattice
            if degree > 0:
                cpe = functional.ComponentPointEvaluation
                pts = ref_el.make_points(sd, 0, degree + sd)
                for d in range(sd):
                    for i in range(len(pts)):
                        l_cur = cpe(ref_el, d, (sd, ), pts[i])
                        nodes.append(l_cur)

        # sets vertices (and in 3d, edges) to have no nodes
        for i in range(sd - 1):
            entity_ids[i] = {}
            for j in range(len(t[i])):
                entity_ids[i][j] = []

        cur = 0

        # set codimension 1 (edges 2d, faces 3d) dof
        pts_facet_0 = ref_el.make_points(sd - 1, 0, sd + degree)
        pts_per_facet = len(pts_facet_0)
        entity_ids[sd - 1] = {}
        for i in range(len(t[sd - 1])):
            entity_ids[sd - 1][i] = list(range(cur, cur + pts_per_facet))
            cur += pts_per_facet

        # internal nodes, if applicable
        entity_ids[sd] = {0: []}
        if degree > 0:
            num_internal_nodes = expansions.polynomial_dimension(
                ref_el, degree - 1)
            entity_ids[sd][0] = list(range(cur, cur + num_internal_nodes * sd))

        super(RTDualSet, self).__init__(nodes, ref_el, entity_ids)
Esempio n. 5
0
    def __init__(self, ref_el, degree, variant, quad_deg):
        sd = ref_el.get_spatial_dimension()
        if sd != 3:
            raise Exception("NedelecDual3D only works on tetrahedra")

        nodes = []

        t = ref_el.get_topology()

        if variant == "integral":
            # edge nodes are \int_F v\cdot t p ds where p \in P_{q-1}(edge)
            # degree is q - 1
            edge = ref_el.get_facet_element().get_facet_element()
            Q = quadrature.make_quadrature(edge, quad_deg)
            Pq = polynomial_set.ONPolynomialSet(edge, degree)
            Pq_at_qpts = Pq.tabulate(Q.get_points())[tuple([0] * (1))]
            for e in range(len(t[1])):
                for i in range(Pq_at_qpts.shape[0]):
                    phi = Pq_at_qpts[i, :]
                    nodes.append(
                        functional.IntegralMomentOfEdgeTangentEvaluation(
                            ref_el, Q, phi, e))

            # face nodes are \int_F v\cdot p dA where p \in P_{q-2}(f)^3 with p \cdot n = 0 (cmp. Monk)
            # these are equivalent to dofs from Fenics book defined by
            # \int_F v\times n \cdot p ds where p \in P_{q-2}(f)^2
            if degree > 0:
                facet = ref_el.get_facet_element()
                Q = quadrature.make_quadrature(facet, quad_deg)
                Pq = polynomial_set.ONPolynomialSet(facet, degree - 1, (sd, ))
                Pq_at_qpts = Pq.tabulate(Q.get_points())[(0, 0)]

                for f in range(len(t[2])):
                    # R is used to map [1,0,0] to tangent1 and [0,1,0] to tangent2
                    R = ref_el.compute_face_tangents(f)

                    # Skip last functionals because we only want p with p \cdot n = 0
                    for i in range(2 * Pq.get_num_members() // 3):
                        phi = Pq_at_qpts[i, ...]
                        phi = numpy.matmul(phi[:-1, ...].T, R)
                        nodes.append(
                            functional.MonkIntegralMoment(ref_el, Q, phi, f))

            # internal nodes. These are \int_T v \cdot p dx where p \in P_{q-3}^3(T)
            if degree > 1:
                Q = quadrature.make_quadrature(ref_el, quad_deg)
                qpts = Q.get_points()
                Pkm2 = polynomial_set.ONPolynomialSet(ref_el, degree - 2)
                zero_index = tuple([0 for i in range(sd)])
                Pkm2_at_qpts = Pkm2.tabulate(qpts)[zero_index]

                for d in range(sd):
                    for i in range(Pkm2_at_qpts.shape[0]):
                        phi_cur = Pkm2_at_qpts[i, :]
                        l_cur = functional.IntegralMoment(
                            ref_el, Q, phi_cur, (d, ), (sd, ))
                        nodes.append(l_cur)

        elif variant == "point":
            num_edges = len(t[1])

            for i in range(num_edges):
                # points to specify P_k on each edge
                pts_cur = ref_el.make_points(1, i, degree + 2)
                for j in range(len(pts_cur)):
                    pt_cur = pts_cur[j]
                    f = functional.PointEdgeTangentEvaluation(
                        ref_el, i, pt_cur)
                    nodes.append(f)

            if degree > 0:  # face tangents
                num_faces = len(t[2])
                for i in range(num_faces):  # loop over faces
                    pts_cur = ref_el.make_points(2, i, degree + 2)
                    for j in range(len(pts_cur)):  # loop over points
                        pt_cur = pts_cur[j]
                        for k in range(2):  # loop over tangents
                            f = functional.PointFaceTangentEvaluation(
                                ref_el, i, k, pt_cur)
                            nodes.append(f)

            if degree > 1:  # internal moments
                Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1))
                qpts = Q.get_points()
                Pkm2 = polynomial_set.ONPolynomialSet(ref_el, degree - 2)
                zero_index = tuple([0 for i in range(sd)])
                Pkm2_at_qpts = Pkm2.tabulate(qpts)[zero_index]

                for d in range(sd):
                    for i in range(Pkm2_at_qpts.shape[0]):
                        phi_cur = Pkm2_at_qpts[i, :]
                        f = functional.IntegralMoment(ref_el, Q, phi_cur,
                                                      (d, ), (sd, ))
                        nodes.append(f)

        entity_ids = {}
        # set to empty
        for i in range(sd + 1):
            entity_ids[i] = {}
            for j in range(len(t[i])):
                entity_ids[i][j] = []

        cur = 0

        # edge dof
        num_pts_per_edge = len(ref_el.make_points(1, 0, degree + 2))
        for i in range(len(t[1])):
            entity_ids[1][i] = list(range(cur, cur + num_pts_per_edge))
            cur += num_pts_per_edge

        # face dof
        if degree > 0:
            num_pts_per_face = len(ref_el.make_points(2, 0, degree + 2))
            for i in range(len(t[2])):
                entity_ids[2][i] = list(range(cur, cur + 2 * num_pts_per_face))
                cur += 2 * num_pts_per_face

        if degree > 1:
            num_internal_dof = Pkm2_at_qpts.shape[0] * sd
            entity_ids[3][0] = list(range(cur, cur + num_internal_dof))

        super(NedelecDual3D, self).__init__(nodes, ref_el, entity_ids)
Esempio n. 6
0
    def __init__(self, ref_el, degree, variant, quad_deg):
        sd = ref_el.get_spatial_dimension()
        if sd != 2:
            raise Exception("Nedelec2D only works on triangles")

        nodes = []

        t = ref_el.get_topology()

        if variant == "integral":
            # edge nodes are \int_F v\cdot t p ds where p \in P_{q-1}(edge)
            # degree is q - 1
            edge = ref_el.get_facet_element()
            Q = quadrature.make_quadrature(edge, quad_deg)
            Pq = polynomial_set.ONPolynomialSet(edge, degree)
            Pq_at_qpts = Pq.tabulate(Q.get_points())[tuple([0] * (sd - 1))]
            for e in range(len(t[sd - 1])):
                for i in range(Pq_at_qpts.shape[0]):
                    phi = Pq_at_qpts[i, :]
                    nodes.append(
                        functional.IntegralMomentOfEdgeTangentEvaluation(
                            ref_el, Q, phi, e))

            # internal nodes. These are \int_T v \cdot p dx where p \in P_{q-2}^2
            if degree > 0:
                Q = quadrature.make_quadrature(ref_el, quad_deg)
                qpts = Q.get_points()
                Pkm1 = polynomial_set.ONPolynomialSet(ref_el, degree - 1)
                zero_index = tuple([0 for i in range(sd)])
                Pkm1_at_qpts = Pkm1.tabulate(qpts)[zero_index]

                for d in range(sd):
                    for i in range(Pkm1_at_qpts.shape[0]):
                        phi_cur = Pkm1_at_qpts[i, :]
                        l_cur = functional.IntegralMoment(
                            ref_el, Q, phi_cur, (d, ), (sd, ))
                        nodes.append(l_cur)

        elif variant == "point":
            num_edges = len(t[1])

            # edge tangents
            for i in range(num_edges):
                pts_cur = ref_el.make_points(1, i, degree + 2)
                for j in range(len(pts_cur)):
                    pt_cur = pts_cur[j]
                    f = functional.PointEdgeTangentEvaluation(
                        ref_el, i, pt_cur)
                    nodes.append(f)

            # internal moments
            if degree > 0:
                Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1))
                qpts = Q.get_points()
                Pkm1 = polynomial_set.ONPolynomialSet(ref_el, degree - 1)
                zero_index = tuple([0 for i in range(sd)])
                Pkm1_at_qpts = Pkm1.tabulate(qpts)[zero_index]

                for d in range(sd):
                    for i in range(Pkm1_at_qpts.shape[0]):
                        phi_cur = Pkm1_at_qpts[i, :]
                        l_cur = functional.IntegralMoment(
                            ref_el, Q, phi_cur, (d, ), (sd, ))
                        nodes.append(l_cur)

        entity_ids = {}

        # set to empty
        for i in range(sd + 1):
            entity_ids[i] = {}
            for j in range(len(t[i])):
                entity_ids[i][j] = []

        cur = 0

        # edges
        num_edge_pts = len(ref_el.make_points(1, 0, degree + 2))

        for i in range(len(t[1])):
            entity_ids[1][i] = list(range(cur, cur + num_edge_pts))
            cur += num_edge_pts

        # moments against P_{degree-1} internally, if degree > 0
        if degree > 0:
            num_internal_dof = sd * Pkm1_at_qpts.shape[0]
            entity_ids[2][0] = list(range(cur, cur + num_internal_dof))

        super(NedelecDual2D, self).__init__(nodes, ref_el, entity_ids)
Esempio n. 7
0
    def __init__(self, ref_el, degree):
        sd = ref_el.get_spatial_dimension()
        if sd != 3:
            raise Exception("NedelecDual3D only works on tetrahedra")

        nodes = []

        t = ref_el.get_topology()

        # how many edges
        num_edges = len(t[1])

        for i in range(num_edges):
            # points to specify P_k on each edge
            pts_cur = ref_el.make_points(1, i, degree + 2)
            for j in range(len(pts_cur)):
                pt_cur = pts_cur[j]
                f = functional.PointEdgeTangentEvaluation(ref_el, i, pt_cur)
                nodes.append(f)

        if degree > 0:  # face tangents
            num_faces = len(t[2])
            for i in range(num_faces):  # loop over faces
                pts_cur = ref_el.make_points(2, i, degree + 2)
                for j in range(len(pts_cur)):  # loop over points
                    pt_cur = pts_cur[j]
                    for k in range(2):  # loop over tangents
                        f = functional.PointFaceTangentEvaluation(
                            ref_el, i, k, pt_cur)
                        nodes.append(f)

        if degree > 1:  # internal moments
            Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1))
            qpts = Q.get_points()
            Pkm2 = polynomial_set.ONPolynomialSet(ref_el, degree - 2)
            zero_index = tuple([0 for i in range(sd)])
            Pkm2_at_qpts = Pkm2.tabulate(qpts)[zero_index]

            for d in range(sd):
                for i in range(Pkm2_at_qpts.shape[0]):
                    phi_cur = Pkm2_at_qpts[i, :]
                    f = functional.IntegralMoment(ref_el, Q, phi_cur, (d, ))
                    nodes.append(f)

        entity_ids = {}
        # set to empty
        for i in range(sd + 1):
            entity_ids[i] = {}
            for j in range(len(t[i])):
                entity_ids[i][j] = []

        cur = 0

        # edge dof
        num_pts_per_edge = len(ref_el.make_points(1, 0, degree + 2))
        for i in range(len(t[1])):
            entity_ids[1][i] = list(range(cur, cur + num_pts_per_edge))
            cur += num_pts_per_edge

        # face dof
        if degree > 0:
            num_pts_per_face = len(ref_el.make_points(2, 0, degree + 2))
            for i in range(len(t[2])):
                entity_ids[2][i] = list(range(cur, cur + 2 * num_pts_per_face))
                cur += 2 * num_pts_per_face

        if degree > 1:
            num_internal_dof = Pkm2_at_qpts.shape[0] * sd
            entity_ids[3][0] = list(range(cur, cur + num_internal_dof))

        super(NedelecDual3D, self).__init__(nodes, ref_el, entity_ids)