Esempio n. 1
0
def NedelecSpace2D(ref_el, k):
    """Constructs a basis for the 2d H(curl) space of the first kind
    which is (P_k)^2 + P_k rot( x )"""
    sd = ref_el.get_spatial_dimension()
    if sd != 2:
        raise Exception("NedelecSpace2D requires 2d reference element")

    vec_Pkp1 = ONPolynomialSet(ref_el, k + 1, (sd, ))

    dimPkp1 = expansions.polynomial_dimension(ref_el, k + 1)
    dimPk = expansions.polynomial_dimension(ref_el, k)
    dimPkm1 = expansions.polynomial_dimension(ref_el, k - 1)

    vec_Pk_indices = list(
        chain(*(range(i * dimPkp1, i * dimPkp1 + dimPk) for i in range(sd))))
    vec_Pk_from_Pkp1 = vec_Pkp1.take(vec_Pk_indices)

    Pkp1 = ONPolynomialSet(ref_el, k + 1)
    PkH = Pkp1.take(list(range(dimPkm1, dimPk)))

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

    Qpts = np.array(Q.get_points())
    Qwts = np.array(Q.get_weights())

    zero_index = tuple([0 for i in range(sd)])

    PkH_at_Qpts = PkH.tabulate(Qpts)[zero_index]
    Pkp1_at_Qpts = Pkp1.tabulate(Qpts)[zero_index]

    PkH_crossx_coeffs = np.zeros(
        (PkH.get_num_members(), sd, Pkp1.get_num_members()), "d")

    def rot_x_foo(a):
        if a == 0:
            return 1, 1.0
        elif a == 1:
            return 0, -1.0

    for i in range(PkH.get_num_members()):
        for j in range(sd):
            (ind, sign) = rot_x_foo(j)
            for k in range(Pkp1.get_num_members()):
                PkH_crossx_coeffs[i, j, k] = sign * sum(
                    Qwts * PkH_at_Qpts[i, :] * Qpts[:, ind] *
                    Pkp1_at_Qpts[k, :])


#                for l in range( len( Qpts ) ):
#                    PkH_crossx_coeffs[i,j,k] += Qwts[ l ] \
#                                                * PkH_at_Qpts[i,l] \
#                                                * Qpts[l][ind] \
#                                                * Pkp1_at_Qpts[k,l] \
#                                                * sign

    PkHcrossx = PolynomialSet(ref_el, k + 1, k + 1,
                              vec_Pkp1.get_expansion_set(), PkH_crossx_coeffs,
                              vec_Pkp1.get_dmats())

    return polynomial_set_union_normalized(vec_Pk_from_Pkp1, PkHcrossx)
Esempio n. 2
0
def RTSpace(ref_el, deg):
    """Constructs a basis for the the Raviart-Thomas space
    (P_k)^d + P_k x"""
    sd = ref_el.get_spatial_dimension()

    vec_Pkp1 = ONPolynomialSet(ref_el, deg + 1, (sd, ))

    dimPkp1 = expansions.polynomial_dimension(ref_el, deg + 1)
    dimPk = expansions.polynomial_dimension(ref_el, deg)
    dimPkm1 = expansions.polynomial_dimension(ref_el, deg - 1)

    vec_Pk_indices = list(
        chain(*(range(i * dimPkp1, i * dimPkp1 + dimPk) for i in range(sd))))
    vec_Pk_from_Pkp1 = vec_Pkp1.take(vec_Pk_indices)

    Pkp1 = ONPolynomialSet(ref_el, deg + 1)
    PkH = Pkp1.take(list(range(dimPkm1, dimPk)))

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

    # have to work on this through "tabulate" interface
    # first, tabulate PkH at quadrature points
    Qpts = np.array(Q.get_points())
    Qwts = np.array(Q.get_weights())

    zero_index = tuple([0 for i in range(sd)])

    PkH_at_Qpts = PkH.tabulate(Qpts)[zero_index]
    Pkp1_at_Qpts = Pkp1.tabulate(Qpts)[zero_index]

    PkHx_coeffs = np.zeros((PkH.get_num_members(), sd, Pkp1.get_num_members()),
                           "d")

    for i in range(PkH.get_num_members()):
        for j in range(sd):
            fooij = PkH_at_Qpts[i, :] * Qpts[:, j] * Qwts
            PkHx_coeffs[i, j, :] = np.dot(Pkp1_at_Qpts, fooij)

    PkHx = PolynomialSet(ref_el, deg, deg + 1, vec_Pkp1.get_expansion_set(),
                         PkHx_coeffs, vec_Pkp1.get_dmats())

    return polynomial_set_union_normalized(vec_Pk_from_Pkp1, PkHx)
def BDFMSpace(ref_el, order):
    sd = ref_el.get_spatial_dimension()
    if sd != 2:
        raise Exception("BDFM_k elements only valid for dim 2")
    # Note that order will be 2.

    # Linear vector valued space. Since the embedding degree of this element
    # is 2, this is implemented by taking the quadratic space and selecting
    # the linear polynomials.
    vec_poly_set = ONPolynomialSet(ref_el, order, (sd, ))
    # Linears are the first three polynomials in each dimension.
    vec_poly_set = vec_poly_set.take([0, 1, 2, 6, 7, 8])

    # Scalar quadratic Lagrange element.
    lagrange_ele = lagrange.Lagrange(ref_el, order)
    # Select the dofs associated with the edges.
    edge_dofs_dict = lagrange_ele.dual.get_entity_ids()[sd - 1]
    edge_dofs = np.array([(edge, dof)
                          for edge, dofs in list(edge_dofs_dict.items())
                          for dof in dofs])

    tangent_polys = lagrange_ele.poly_set.take(edge_dofs[:, 1])
    new_coeffs = np.zeros(
        (tangent_polys.get_num_members(), sd, tangent_polys.coeffs.shape[-1]))

    # Outer product of the tangent vectors with the quadratic edge polynomials.
    for i, (edge, dof) in enumerate(edge_dofs):
        tangent = ref_el.compute_edge_tangent(edge)

        new_coeffs[i, :, :] = np.outer(tangent, tangent_polys.coeffs[i, :])

    bubble_set = PolynomialSet(ref_el, order, order,
                               vec_poly_set.get_expansion_set(), new_coeffs,
                               vec_poly_set.get_dmats())

    element_set = polynomial_set_union_normalized(bubble_set, vec_poly_set)
    return element_set
Esempio n. 4
0
def NedelecSpace3D(ref_el, k):
    """Constructs a nodal basis for the 3d first-kind Nedelec space"""
    sd = ref_el.get_spatial_dimension()
    if sd != 3:
        raise Exception("NedelecSpace3D requires 3d reference element")

    vec_Pkp1 = ONPolynomialSet(ref_el, k + 1, (sd, ))

    dimPkp1 = expansions.polynomial_dimension(ref_el, k + 1)
    dimPk = expansions.polynomial_dimension(ref_el, k)
    if k > 0:
        dimPkm1 = expansions.polynomial_dimension(ref_el, k - 1)
    else:
        dimPkm1 = 0

    vec_Pk_indices = list(
        chain(*(range(i * dimPkp1, i * dimPkp1 + dimPk) for i in range(sd))))
    vec_Pk = vec_Pkp1.take(vec_Pk_indices)

    vec_Pke_indices = list(
        chain(*(range(i * dimPkp1 + dimPkm1, i * dimPkp1 + dimPk)
                for i in range(sd))))

    vec_Pke = vec_Pkp1.take(vec_Pke_indices)

    Pkp1 = ONPolynomialSet(ref_el, k + 1)

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

    Qpts = np.array(Q.get_points())
    Qwts = np.array(Q.get_weights())

    zero_index = tuple([0 for i in range(sd)])

    PkCrossXcoeffs = np.zeros(
        (vec_Pke.get_num_members(), sd, Pkp1.get_num_members()), "d")

    Pke_qpts = vec_Pke.tabulate(Qpts)[zero_index]
    Pkp1_at_Qpts = Pkp1.tabulate(Qpts)[zero_index]

    for i in range(vec_Pke.get_num_members()):
        for j in range(sd):  # vector components
            qwts_cur_bf_val = (
                Qpts[:, (j + 2) % 3] * Pke_qpts[i, (j + 1) % 3, :] -
                Qpts[:, (j + 1) % 3] * Pke_qpts[i, (j + 2) % 3, :]) * Qwts
            PkCrossXcoeffs[i, j, :] = np.dot(Pkp1_at_Qpts, qwts_cur_bf_val)


#            for k in range( Pkp1.get_num_members() ):
#                 PkCrossXcoeffs[i,j,k] = sum( Qwts * cur_bf_val * Pkp1_at_Qpts[k,:] )
#                for l in range( len( Qpts ) ):
#                    cur_bf_val = Qpts[l][(j+2)%3] \
#                                 * Pke_qpts[i,(j+1)%3,l] \
#                                 - Qpts[l][(j+1)%3] \
#                                 * Pke_qpts[i,(j+2)%3,l]
#                    PkCrossXcoeffs[i,j,k] += Qwts[l] \
#                                             * cur_bf_val \
#                                             * Pkp1_at_Qpts[k,l]

    PkCrossX = PolynomialSet(ref_el, k + 1, k + 1,
                             vec_Pkp1.get_expansion_set(), PkCrossXcoeffs,
                             vec_Pkp1.get_dmats())
    return polynomial_set_union_normalized(vec_Pk, PkCrossX)