def convert_finiteelement(element, **kwargs): cell = as_fiat_cell(element.cell()) if element.family() == "Quadrature": degree = element.degree() scheme = element.quadrature_scheme() if degree is None or scheme is None: raise ValueError("Quadrature scheme and degree must be specified!") return finat.QuadratureElement(cell, degree, scheme), set() elif element.family() == "Bernstein": return fiat_compat(element), set() lmbda = supported_elements[element.family()] if lmbda is None: if element.cell().cellname() == "quadrilateral": # Handle quadrilateral short names like RTCF and RTCE. element = element.reconstruct(cell=quadrilateral_tpc) elif element.cell().cellname() == "hexahedron": # Handle hexahedron short names like NCF and NCE. element = element.reconstruct(cell=hexahedron_tpc) else: raise ValueError("%s is supported, but handled incorrectly" % element.family()) finat_elem, deps = _create_element(element, **kwargs) return finat.FlattenedDimensions(finat_elem), deps kind = element.variant() if kind is None: kind = 'equispaced' # default variant if element.family() == "Lagrange": if kind == 'equispaced': lmbda = finat.Lagrange elif kind == 'spectral' and element.cell().cellname() == 'interval': lmbda = finat.GaussLobattoLegendre else: raise ValueError("Variant %r not supported on %s" % (kind, element.cell())) elif element.family() == "Discontinuous Lagrange": kind = element.variant() or 'equispaced' if kind == 'equispaced': lmbda = finat.DiscontinuousLagrange elif kind == 'spectral' and element.cell().cellname() == 'interval': lmbda = finat.GaussLegendre else: raise ValueError("Variant %r not supported on %s" % (kind, element.cell())) return lmbda(cell, element.degree()), set()
def convert_finiteelement(element): cell = as_fiat_cell(element.cell()) if element.family() == "Quadrature": degree = element.degree() scheme = element.quadrature_scheme() if degree is None or scheme is None: raise ValueError("Quadrature scheme and degree must be specified!") return finat.QuadratureElement(cell, degree, scheme) if element.family() not in supported_elements: return fiat_compat(element) lmbda = supported_elements.get(element.family()) if lmbda is None: if element.cell().cellname() != "quadrilateral": raise ValueError("%s is supported, but handled incorrectly" % element.family()) # Handle quadrilateral short names like RTCF and RTCE. element = element.reconstruct(cell=quad_tpc) return finat.QuadrilateralElement(create_element(element)) kind = element.variant() if kind is None: kind = 'equispaced' # default variant if element.family() == "Lagrange": if kind == 'equispaced': lmbda = finat.Lagrange elif kind == 'spectral' and element.cell().cellname() == 'interval': lmbda = finat.GaussLobattoLegendre else: raise ValueError("Variant %r not supported on %s" % (kind, element.cell())) elif element.family() == "Discontinuous Lagrange": kind = element.variant() or 'equispaced' if kind == 'equispaced': lmbda = finat.DiscontinuousLagrange elif kind == 'spectral' and element.cell().cellname() == 'interval': lmbda = finat.GaussLegendre else: raise ValueError("Variant %r not supported on %s" % (kind, element.cell())) return lmbda(cell, element.degree())
def rebuild_dg(element, expr, rt_var_name): # To tabulate on the given element (which is on a different mesh to the # expression) we must do so at runtime. We therefore create a quadrature # element with runtime points to evaluate for each point in the element's # dual basis. This exists on the same reference cell as the input element # and we can interpolate onto it before mapping the result back onto the # target space. expr_tdim = expr.ufl_domain().topological_dimension() # Need point evaluations and matching weights from dual basis. # This could use FIAT's dual basis as below: # num_points = sum(len(dual.get_point_dict()) for dual in element.fiat_equivalent.dual_basis()) # weights = [] # for dual in element.fiat_equivalent.dual_basis(): # pts = dual.get_point_dict().keys() # for p in pts: # for w, _ in dual.get_point_dict()[p]: # weights.append(w) # assert len(weights) == num_points # but for now we just fix the values to what we know works: if element.degree != 0 or not isinstance(element.cell, FIAT.reference_element.Point): raise NotImplementedError( "Cross mesh interpolation only implemented for P0DG on vertex cells." ) num_points = 1 weights = [1.] * num_points # gem.Variable name starting with rt_ forces TSFC runtime tabulation assert rt_var_name.startswith("rt_") runtime_points_expr = gem.Variable(rt_var_name, (num_points, expr_tdim)) rule_pointset = finat.point_set.UnknownPointSet(runtime_points_expr) try: expr_fiat_cell = as_fiat_cell(expr.ufl_element().cell()) except AttributeError: # expression must be pure function of spatial coordinates so # domain has correct ufl cell expr_fiat_cell = as_fiat_cell(expr.ufl_domain().ufl_cell()) rule = finat.quadrature.QuadratureRule(rule_pointset, weights=weights) return finat.QuadratureElement(expr_fiat_cell, rule)
def convert_finiteelement(element, **kwargs): cell = as_fiat_cell(element.cell()) if element.family() == "Quadrature": degree = element.degree() scheme = element.quadrature_scheme() if degree is None or scheme is None: raise ValueError("Quadrature scheme and degree must be specified!") return finat.QuadratureElement(cell, degree, scheme), set() elif element.family() == "Bernstein": return fiat_compat(element), set() lmbda = supported_elements[element.family()] if lmbda is None: if element.cell().cellname() == "quadrilateral": # Handle quadrilateral short names like RTCF and RTCE. element = element.reconstruct(cell=quadrilateral_tpc) elif element.cell().cellname() == "hexahedron": # Handle hexahedron short names like NCF and NCE. element = element.reconstruct(cell=hexahedron_tpc) else: raise ValueError("%s is supported, but handled incorrectly" % element.family()) finat_elem, deps = _create_element(element, **kwargs) return finat.FlattenedDimensions(finat_elem), deps kind = element.variant() if kind is None: kind = 'spectral' if element.cell().cellname( ) == 'interval' else 'equispaced' # default variant if element.family() == "Lagrange": if kind == 'equispaced': lmbda = finat.Lagrange elif kind == 'spectral' and element.cell().cellname() == 'interval': lmbda = finat.GaussLobattoLegendre elif kind in ['mgd', 'feec', 'qb', 'mse']: degree = element.degree() shift_axes = kwargs["shift_axes"] restriction = kwargs["restriction"] deps = {"shift_axes", "restriction"} return finat.RuntimeTabulated(cell, degree, variant=kind, shift_axes=shift_axes, restriction=restriction), deps else: raise ValueError("Variant %r not supported on %s" % (kind, element.cell())) elif element.family() in [ "Discontinuous Lagrange", "Discontinuous Lagrange L2" ]: if kind == 'equispaced': lmbda = finat.DiscontinuousLagrange elif kind == 'spectral' and element.cell().cellname() == 'interval': lmbda = finat.GaussLegendre elif kind in ['mgd', 'feec', 'qb', 'mse']: degree = element.degree() shift_axes = kwargs["shift_axes"] restriction = kwargs["restriction"] deps = {"shift_axes", "restriction"} return finat.RuntimeTabulated(cell, degree, variant=kind, shift_axes=shift_axes, restriction=restriction, continuous=False), deps else: raise ValueError("Variant %r not supported on %s" % (kind, element.cell())) elif element.family() == ["DPC", "DPC L2"]: if element.cell().geometric_dimension() == 2: element = element.reconstruct(cell=ufl.cell.hypercube(2)) elif element.cell().geometric_dimension() == 3: element = element.reconstruct(cell=ufl.cell.hypercube(3)) elif element.family() == "S": if element.cell().geometric_dimension() == 2: element = element.reconstruct(cell=ufl.cell.hypercube(2)) elif element.cell().geometric_dimension() == 3: element = element.reconstruct(cell=ufl.cell.hypercube(3)) return lmbda(cell, element.degree()), set()