def _generate_edge_dofs(cell, degree): """Generate dofs on edges. On each edge, let n be its normal. We need to integrate u.n and u.t against the first Legendre polynomial (constant) and u.n against the second (linear). """ dofs = [] dof_ids = {} offset = 0 sd = 2 facet = cell.get_facet_element() # Facet nodes are \int_F v\cdot n p ds where p \in P_{q-1} # degree is q - 1 Q = make_quadrature(facet, 6) Pq = ONPolynomialSet(facet, 1) Pq_at_qpts = Pq.tabulate(Q.get_points())[tuple([0] * (sd - 1))] for f in range(3): phi0 = Pq_at_qpts[0, :] dofs.append(IntegralMomentOfNormalEvaluation(cell, Q, phi0, f)) dofs.append(IntegralMomentOfTangentialEvaluation(cell, Q, phi0, f)) phi1 = Pq_at_qpts[1, :] dofs.append(IntegralMomentOfNormalEvaluation(cell, Q, phi1, f)) num_new_dofs = 3 dof_ids[f] = list(range(offset, offset + num_new_dofs)) offset += num_new_dofs return (dofs, dof_ids)
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)
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)
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_edge_dofs(self, cell, degree, offset, variant, quad_deg): """Generate degrees of freedoms (dofs) for entities of codimension 1 (edges).""" # (degree+1) tangential component point evaluation degrees of # freedom per entity of codimension 1 (edges) dofs = [] ids = {} if variant == "integral": edge = cell.construct_subelement(1) 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(cell.get_topology()[1])): for i in range(Pq_at_qpts.shape[0]): phi = Pq_at_qpts[i, :] dofs.append(functional.IntegralMomentOfEdgeTangentEvaluation(cell, Q, phi, e)) jj = Pq_at_qpts.shape[0] * e ids[e] = list(range(offset + jj, offset + jj + Pq_at_qpts.shape[0])) elif variant == "point": for edge in range(len(cell.get_topology()[1])): # Create points for evaluation of tangential components points = cell.make_points(1, edge, degree + 2) # A tangential component evaluation for each point dofs += [Tangent(cell, edge, point) for point in points] # Associate these dofs with this edge i = len(points) * edge ids[edge] = list(range(offset + i, offset + i + len(points))) return (dofs, ids)
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)
def _fiat_scheme(ref_el, degree): """Get quadrature scheme from FIAT interface""" # Number of points per axis for exact integration num_points_per_axis = (degree + 1 + 1) // 2 # Create and return FIAT quadrature rule return make_quadrature(ref_el, num_points_per_axis)
def __init__(self, ref_el, degree): # Initialize containers for map: mesh_entity -> dof number and # dual basis entity_ids = {} nodes = [] sd = ref_el.get_spatial_dimension() t = ref_el.get_topology() # Define each functional for the dual set # 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 if degree > 1: Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1)) qpts = Q.get_points() Nedel = nedelec.Nedelec(ref_el, degree - 1) Nedfs = Nedel.get_nodal_basis() zero_index = tuple([0 for i in range(sd)]) Ned_at_qpts = Nedfs.tabulate(qpts)[zero_index] for i in range(len(Ned_at_qpts)): phi_cur = Ned_at_qpts[i, :] l_cur = functional.FrobeniusIntegralMoment(ref_el, Q, phi_cur) 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 > 1: num_internal_nodes = len(Ned_at_qpts) entity_ids[sd][0] = list(range(cur, cur + num_internal_nodes)) super().__init__(nodes, ref_el, entity_ids)
def __init__(self, ref_el, degree): # Initialize containers for map: mesh_entity -> dof number and # dual basis entity_ids = {} nodes = [] sd = ref_el.get_spatial_dimension() t = ref_el.get_topology() # Define each functional for the dual set # 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 if degree > 1: Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1)) qpts = Q.get_points() Nedel = nedelec.Nedelec(ref_el, degree - 1) Nedfs = Nedel.get_nodal_basis() zero_index = tuple([0 for i in range(sd)]) Ned_at_qpts = Nedfs.tabulate(qpts)[zero_index] for i in range(len(Ned_at_qpts)): phi_cur = Ned_at_qpts[i, :] l_cur = functional.FrobeniusIntegralMoment(ref_el, Q, phi_cur) 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 > 1: num_internal_nodes = len(Ned_at_qpts) entity_ids[sd][0] = list(range(cur, cur + num_internal_nodes)) super(BDMDualSet, self).__init__(nodes, ref_el, entity_ids)
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)
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)
def __init__(self, cell, order): assert cell == UFCInterval() and order == 3 entity_ids = {0: {0: [0], 1: [1]}, 1: {0: [2, 3]}} vertnodes = [PointEvaluation(cell, xx) for xx in cell.vertices] Q = make_quadrature(cell, 3) # 1st integral moment node is integral(1*f(x)*dx) ones = np.asarray([1.0 for x in Q.pts]) # 2nd integral moment node is integral(x*f(x)*dx) xs = np.asarray([x for (x, ) in Q.pts]) intnodes = [IntegralMoment(cell, Q, ones), IntegralMoment(cell, Q, xs)] nodes = vertnodes + intnodes super().__init__(nodes, cell, entity_ids)
def __init__(self, cell, degree): if not degree == 2: raise ValueError("Nonconforming Arnold-Winther elements are" "only defined for degree 2.") dofs = [] dof_ids = {} dof_ids[0] = {0: [], 1: [], 2: []} dof_ids[1] = {0: [], 1: [], 2: []} dof_ids[2] = {0: []} dof_cur = 0 # no vertex dofs # proper edge dofs now (not the contraints) # moments of normal . sigma against constants and linears. for entity_id in range(3): # a triangle has 3 edges 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, 2) 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 i, y in enumerate(v1v2t): for j, x in enumerate(y): for k in range(len(Q.pts)): fatqp[i, j, k] = x dofs.append(FIM(cell, Q, fatqp)) dof_ids[2][0] = list(range(dof_cur, dof_cur + 3)) dof_cur += 3 # put the constraint dofs last. for entity_id in range(3): dof = IntegralLegendreNormalNormalMoment(cell, entity_id, 2, 6) dofs.append(dof) dof_ids[1][entity_id].append(dof_cur) dof_cur += 1 super(ArnoldWintherNCDual, self).__init__(dofs, cell, dof_ids)
def _setupQuadrature(self): """ Setup quadrature rule for reference cell. """ from FIAT.reference_element import default_simplex from FIAT.quadrature import make_quadrature from FIATQuadrature import CollocatedQuadratureRule if not self.collocateQuad: q = make_quadrature(default_simplex(1), self.order) else: q = CollocatedQuadratureRule(default_simplex(1), self.order) return q
def DivergenceDubinerMoments(cell, start_deg, stop_deg, comp_deg): onp = ONPolynomialSet(cell, stop_deg) Q = make_quadrature(cell, comp_deg) pts = Q.get_points() onp = onp.tabulate(pts, 0)[0, 0] ells = [] for ii in range((start_deg) * (start_deg + 1) // 2, (stop_deg + 1) * (stop_deg + 2) // 2): ells.append(IntegralMomentOfDivergence(cell, Q, onp[ii, :])) return ells
def _fiat_scheme(ref_el, degree): """Get quadrature scheme from FIAT interface""" # Number of points per axis for exact integration num_points_per_axis = (degree + 1 + 1) // 2 # Check for excess if num_points_per_axis > 30: dim = ref_el.get_spatial_dimension() raise RuntimeError("Requested a quadrature rule with %d points per direction (%d points)" % (num_points_per_axis, num_points_per_axis**dim)) # Create and return FIAT quadrature rule return make_quadrature(ref_el, num_points_per_axis)
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 = polynomial_set.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 = polynomial_set.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 = numpy.array(Q.get_points()) Qwts = numpy.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 = numpy.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, :] = numpy.dot(Pkp1_at_Qpts, fooij) PkHx = polynomial_set.PolynomialSet(ref_el, deg, deg + 1, vec_Pkp1.get_expansion_set(), PkHx_coeffs, vec_Pkp1.get_dmats()) return polynomial_set.polynomial_set_union_normalized(vec_Pk_from_Pkp1, PkHx)
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)
def __init__(self, ref_el, degree, variant, quad_deg): # Initialize containers for map: mesh_entity -> dof number and # dual basis 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 if degree > 1: Q = quadrature.make_quadrature(ref_el, quad_deg) qpts = Q.get_points() Nedel = nedelec.Nedelec(ref_el, degree - 1, variant) Nedfs = Nedel.get_nodal_basis() zero_index = tuple([0 for i in range(sd)]) Ned_at_qpts = Nedfs.tabulate(qpts)[zero_index] for i in range(len(Ned_at_qpts)): phi_cur = Ned_at_qpts[i, :] l_cur = functional.FrobeniusIntegralMoment( ref_el, Q, phi_cur) nodes.append(l_cur) elif variant == "point": # Define each functional for the dual set # 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 if degree > 1: Q = quadrature.make_quadrature(ref_el, 2 * (degree + 1)) qpts = Q.get_points() Nedel = nedelec.Nedelec(ref_el, degree - 1, variant) Nedfs = Nedel.get_nodal_basis() zero_index = tuple([0 for i in range(sd)]) Ned_at_qpts = Nedfs.tabulate(qpts)[zero_index] for i in range(len(Ned_at_qpts)): phi_cur = Ned_at_qpts[i, :] l_cur = functional.FrobeniusIntegralMoment( ref_el, Q, phi_cur) 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 > 1: num_internal_nodes = len(Ned_at_qpts) entity_ids[sd][0] = list(range(cur, cur + num_internal_nodes)) super(BDMDualSet, self).__init__(nodes, ref_el, entity_ids)
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)
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)
"text.usetex": True, "linewidth": 4, "figure.figsize": fig_size, } ) # subplots_adjust(left=0.06,right=0.975,bottom=0.08,top=0.94) subplots_adjust(left=0.15, right=0.95, bottom=0.06, top=0.95) set_sizes_talk() rcParams.update({"backend": "png"}) m = 5 n = 100 u = Lagrange.Lagrange(1, m, shapes.line_point_family_lgl) ufs = u.function_space() q = quadrature.make_quadrature(1, n) x = q.get_points() t = ufs.tabulate_jet(1, x) B = t[0][(0,)] D = t[1][(1,)] subplot(211) p = [plot(x, B[i], linewidth=2) for i in range(m + 1)] ylabel("Basis functions") # xlabel('$\hat{x}$') subplot(212) p = [plot(x, D[i], linewidth=2) for i in range(m + 1)] ylim(-10, 10) ylabel("Derivatives") xlabel("$\hat{x}$") savefig("lgl.png")
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 = polynomial_set.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 = polynomial_set.ONPolynomialSet(ref_el, k + 1) Q = quadrature.make_quadrature(ref_el, 2 * (k + 1)) Qpts = numpy.array(Q.get_points()) Qwts = numpy.array(Q.get_weights()) zero_index = tuple([0 for i in range(sd)]) PkCrossXcoeffs = numpy.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, :] = numpy.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 = polynomial_set.PolynomialSet(ref_el, k + 1, k + 1, vec_Pkp1.get_expansion_set(), PkCrossXcoeffs, vec_Pkp1.get_dmats()) return polynomial_set.polynomial_set_union_normalized(vec_Pk, PkCrossX)
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)
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)
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)
import numpy from FIAT.polynomial_set import mis from FIAT.reference_element import default_simplex from FIAT.quadrature import make_quadrature order = 1 quadrature = make_quadrature(default_simplex(1), order) from FIAT.lagrange import Lagrange degree = 1 element = Lagrange(default_simplex(1), degree) vertices = [n.get_point_dict().keys()[0] for n in element.dual.get_nodes()] quadpts = numpy.array(quadrature.get_points(), dtype=numpy.float64) quadwts = numpy.array(quadrature.get_weights(), dtype=numpy.float64) numQuadPts = len(quadpts) evals = element.get_nodal_basis().tabulate(quadrature.get_points(), 1) basis = numpy.array(evals[mis(1, 0)[0]], dtype=numpy.float64).transpose() numBasis = element.get_nodal_basis().get_num_members() basisDeriv = numpy.array([evals[alpha] for alpha in mis(1, 1)], dtype=numpy.float64).transpose() print "order: %d" % order print "degree: %d" % degree print "numQuadPts: %d" % numQuadPts print "basis:" print basis print "basisDeriv:" print basisDeriv
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 = polynomial_set.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 = polynomial_set.ONPolynomialSet(ref_el, k + 1) Q = quadrature.make_quadrature(ref_el, 2 * (k + 1)) Qpts = numpy.array(Q.get_points()) Qwts = numpy.array(Q.get_weights()) zero_index = tuple([0 for i in range(sd)]) PkCrossXcoeffs = numpy.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, :] = numpy.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 = polynomial_set.PolynomialSet(ref_el, k + 1, k + 1, vec_Pkp1.get_expansion_set(), PkCrossXcoeffs, vec_Pkp1.get_dmats()) return polynomial_set.polynomial_set_union_normalized(vec_Pk, PkCrossX)
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 = polynomial_set.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 = polynomial_set.ONPolynomialSet(ref_el, k + 1) PkH = Pkp1.take(list(range(dimPkm1, dimPk))) Q = quadrature.make_quadrature(ref_el, 2 * k + 2) Qpts = numpy.array(Q.get_points()) Qwts = numpy.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 = numpy.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 = polynomial_set.PolynomialSet(ref_el, k + 1, k + 1, vec_Pkp1.get_expansion_set(), PkH_crossx_coeffs, vec_Pkp1.get_dmats()) return polynomial_set.polynomial_set_union_normalized(vec_Pk_from_Pkp1, PkHcrossx)
'ytick.labelsize': 16, 'text.usetex': True, 'linewidth': 4, 'figure.figsize': fig_size }) #subplots_adjust(left=0.06,right=0.975,bottom=0.08,top=0.94) subplots_adjust(left=0.15, right=0.95, bottom=0.06, top=0.95) set_sizes_talk() rcParams.update({'backend': 'png'}) m = 5 n = 100 u = Lagrange.Lagrange(1, m, shapes.line_point_family_lgl) ufs = u.function_space() q = quadrature.make_quadrature(1, n) x = q.get_points() t = ufs.tabulate_jet(1, x) B = t[0][(0, )] D = t[1][(1, )] subplot(211) p = [plot(x, B[i], linewidth=2) for i in range(m + 1)] ylabel('Basis functions') #xlabel('$\hat{x}$') subplot(212) p = [plot(x, D[i], linewidth=2) for i in range(m + 1)] ylim(-10, 10) ylabel('Derivatives') xlabel('$\hat{x}$') savefig('lgl.png')
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)