Source code for FIAT.lagrange

# Copyright (C) 2008 Robert C. Kirby (Texas Tech University)
# Modified by Andrew T. T. McRae (Imperial College London)
#
# This file is part of FIAT (https://www.fenicsproject.org)
#
# SPDX-License-Identifier:    LGPL-3.0-or-later

from FIAT import finite_element, polynomial_set, dual_set, functional
from FIAT.orientation_utils import make_entity_permutations_simplex
from FIAT.barycentric_interpolation import LagrangePolynomialSet, get_lagrange_points
from FIAT.reference_element import LINE
from FIAT.check_format_variant import parse_lagrange_variant


[docs] class LagrangeDualSet(dual_set.DualSet): """The dual basis for Lagrange elements. This class works for simplicial complexes of any dimension. Nodes are point evaluation at recursively-defined points. :arg ref_el: The simplicial complex. :arg degree: The polynomial degree. :arg point_variant: The point distribution variant passed on to recursivenodes. :arg sort_entities: A flag to sort entities by support vertex ids. If false then entities are sorted first by dimension and then by entity id. The DOFs are always sorted by the entity ordering and then lexicographically by lattice multiindex. """ def __init__(self, ref_el, degree, point_variant="equispaced", sort_entities=False): nodes = [] entity_ids = {} entity_permutations = {} top = ref_el.get_topology() for dim in sorted(top): entity_ids[dim] = {} entity_permutations[dim] = {} perms = {0: [0]} if dim == 0 else make_entity_permutations_simplex(dim, degree - dim) for entity in sorted(top[dim]): entity_permutations[dim][entity] = perms entities = [(dim, entity) for dim in sorted(top) for entity in sorted(top[dim])] if sort_entities: # sort the entities by support vertex ids support = [top[dim][entity] for dim, entity in entities] entities = [entity for verts, entity in sorted(zip(support, entities))] # make nodes by getting points # need to do this entity-by-entity for dim, entity in entities: cur = len(nodes) pts_cur = ref_el.make_points(dim, entity, degree, variant=point_variant) nodes.extend(functional.PointEvaluation(ref_el, x) for x in pts_cur) entity_ids[dim][entity] = list(range(cur, len(nodes))) super().__init__(nodes, ref_el, entity_ids, entity_permutations)
[docs] class Lagrange(finite_element.CiarletElement): """The Lagrange finite element. :arg ref_el: The reference element, which could be a standard FIAT simplex or a split complex :arg degree: The polynomial degree :arg variant: A comma-separated string that may specify the type of point distribution and the splitting strategy if a macro element is desired. Either option may be omitted. The default point type is equispaced and the default splitting strategy is None. Example: variant='gll' gives a standard unsplit point distribution with spectral points. variant='equispaced,Iso(2)' with degree=1 gives the P2:P1 iso element. variant='Alfeld' can be used to obtain a barycentrically refined macroelement for Scott-Vogelius. :arg sort_entities: A flag to sort entities by support vertex ids. If false then entities are sorted first by dimension and then by entity id. The DOFs are always sorted by the entity ordering and then lexicographically by lattice multiindex. """ def __init__(self, ref_el, degree, variant="equispaced", sort_entities=False): splitting, point_variant = parse_lagrange_variant(variant) if splitting is not None: ref_el = splitting(ref_el) dual = LagrangeDualSet(ref_el, degree, point_variant=point_variant, sort_entities=sort_entities) if ref_el.shape == LINE: # In 1D we can use the primal basis as the expansion set, # avoiding any round-off coming from a basis transformation points = get_lagrange_points(dual) poly_set = LagrangePolynomialSet(ref_el, points) else: poly_variant = "bubble" if ref_el.is_macrocell() else None poly_set = polynomial_set.ONPolynomialSet(ref_el, degree, variant=poly_variant) formdegree = 0 # 0-form super().__init__(poly_set, dual, degree, formdegree)