def _generate_dofs(cell, entity_dim, degree, offset): """generate degrees of freedom for enetities of dimension entity_dim Input: all obvious except offset -- the current first available dof id. Output: dofs -- an array of dofs associated to entities in that dim dof_ids -- a dict mapping entity_id to the range of indices of dofs associated to it. On a k-face for degree r, the dofs are given by the value of t^T u t evaluated at points enough to control P(r-k+1) for all the edge tangents of the face. `cell.make_points(entity_dim, entity_id, degree + 2)` happens to generate exactly those points needed. """ dofs = [] dof_ids = {} num_entities = len(cell.get_topology()[entity_dim]) for entity_id in range(num_entities): pts = cell.make_points(entity_dim, entity_id, degree + 2) tangents = cell.compute_face_edge_tangents(entity_dim, entity_id) dofs += [ InnerProduct(cell, t, t, pt) for pt in pts for t in tangents ] num_new_dofs = len(pts) * len(tangents) dof_ids[entity_id] = list(range(offset, offset + num_new_dofs)) offset += num_new_dofs return (dofs, dof_ids)
def _generate_edge_dofs(cell, degree, offset): """Generate dofs on edges. On each edge, let n be its normal. For degree=r, the scalar function n^T u n is evaluated at points enough to control P(r). """ dofs = [] dof_ids = {} for entity_id in range(3): # a triangle has 3 edges pts = cell.make_points(1, entity_id, degree + 2) # edges are 1D normal = cell.compute_scaled_normal(entity_id) dofs += [InnerProduct(cell, normal, normal, pt) for pt in pts] num_new_dofs = len(pts) # 1 dof per point on edge dof_ids[entity_id] = list(range(offset, offset + num_new_dofs)) offset += num_new_dofs return (dofs, dof_ids)
def _generate_trig_dofs(cell, degree, offset): """Generate dofs on edges. On each triangle, for degree=r, the three components u11, u12, u22 are evaluated at points enough to control P(r-1). """ dofs = [] dof_ids = {} pts = cell.make_points(2, 0, degree + 2) # 2D trig #0 e1 = np.array([1.0, 0.0]) # euclidean basis 1 e2 = np.array([0.0, 1.0]) # euclidean basis 2 basis = [(e1, e1), (e1, e2), (e2, e2)] # basis for symmetric matrix for (v1, v2) in basis: dofs += [InnerProduct(cell, v1, v2, pt) for pt in pts] num_dofs = 3 * len(pts) # 3 dofs per trig dof_ids[0] = list(range(offset, offset + num_dofs)) return (dofs, dof_ids)
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)