Exemplo n.º 1
0
def _generate_physical_offsets(ufl_element, offset=0):
    """Generate offsets: i.e value offset for each basis function
    relative to a physical element representation."""
    cell = ufl_element.cell()
    gdim = cell.geometric_dimension()
    tdim = cell.topological_dimension()

    # Refer to reference if gdim == tdim. This is a hack to support
    # more stuff (in particular restricted elements)
    if gdim == tdim:
        return _generate_reference_offsets(create_element(ufl_element))

    if isinstance(ufl_element, ufl.MixedElement):
        offsets = []
        for e in ufl_element.sub_elements():
            offsets += _generate_physical_offsets(e, offset)
            # e is a ufl element, so value_size means the physical value size
            offset += e.value_size()
        return offsets

    elif isinstance(ufl_element, ufl.EnrichedElement):
        offsets = []
        for e in ufl_element._elements:  # TODO: Avoid private member access
            offsets += _generate_physical_offsets(e, offset)
        return offsets

    elif isinstance(ufl_element, ufl.FiniteElement):
        fiat_element = create_element(ufl_element)
        return [offset] * fiat_element.space_dimension()

    else:
        raise NotImplementedError("This element combination is not implemented")
Exemplo n.º 2
0
def compute_shapes(form: ufl.Form):
    """Computes the shapes of the cell tensor, coefficient & coordinate arrays for a form"""

    # Cell tensor
    elements = tuple(arg.ufl_element() for arg in form.arguments())
    fiat_elements = (create_element(element) for element in elements)
    element_dims = tuple(fe.space_dimension() for fe in fiat_elements)
    A_shape = element_dims

    # Coefficient arrays
    ws_shapes = []
    for coefficient in form.coefficients():
        w_element = coefficient.ufl_element()
        w_dim = create_element(w_element).space_dimension()
        ws_shapes.append((w_dim,))
    if len(ws_shapes) > 0:
        max_w_dim = sorted(ws_shapes, key=lambda w_dim: np.prod(w_dim))[-1]
        w_full_shape = (len(ws_shapes), ) + max_w_dim
    else:
        w_full_shape = (0,)

    # Coordinate dofs array
    num_vertices_per_cell = form.ufl_cell().num_vertices()
    gdim = form.ufl_cell().geometric_dimension()
    coords_shape = (num_vertices_per_cell, gdim)

    return A_shape, w_full_shape, coords_shape
def _generate_physical_offsets(ufl_element, offset=0):
    """Generate offsets: i.e value offset for each basis function
    relative to a physical element representation."""
    offsets = []

    # Refer to reference if gdim == tdim. This is a hack to support
    # more stuff (in particular restricted elements)
    gdim = ufl_element.cell().geometric_dimension()
    tdim = ufl_element.cell().topological_dimension()
    if (gdim == tdim):
        return _generate_reference_offsets(create_element(ufl_element))

    if isinstance(ufl_element, ufl.MixedElement):
        for e in ufl_element.sub_elements():
            offsets += _generate_physical_offsets(e, offset)
            offset += _value_size(e)
    elif isinstance(ufl_element, ufl.EnrichedElement):
        for e in ufl_element._elements:
            offsets += _generate_physical_offsets(e, offset)
    elif isinstance(ufl_element, ufl.FiniteElement):
        element = create_element(ufl_element)
        offsets = [offset] * element.space_dimension()
    else:
        raise NotImplementedError, \
            "This element combination is not implemented"
    return offsets
Exemplo n.º 4
0
def _generate_physical_offsets(ufl_element, offset=0):
    """Generate offsets: i.e value offset for each basis function
    relative to a physical element representation."""
    cell = ufl_element.cell()
    gdim = cell.geometric_dimension()
    tdim = cell.topological_dimension()

    # Refer to reference if gdim == tdim. This is a hack to support more
    # stuff (in particular restricted elements)
    if gdim == tdim:
        return _generate_reference_offsets(create_element(ufl_element))

    if isinstance(ufl_element, ufl.MixedElement):
        offsets = []
        for e in ufl_element.sub_elements():
            offsets += _generate_physical_offsets(e, offset)
            # e is a ufl element, so value_size means the physical value size
            offset += e.value_size()
        return offsets
    elif isinstance(ufl_element, ufl.EnrichedElement):
        offsets = []
        for e in ufl_element._elements:  # TODO: Avoid private member access
            offsets += _generate_physical_offsets(e, offset)
        return offsets
    elif isinstance(ufl_element, ufl.FiniteElement):
        fiat_element = create_element(ufl_element)
        return [offset] * fiat_element.space_dimension()
    else:
        raise NotImplementedError(
            "This element combination is not implemented")
def _generate_physical_offsets(ufl_element, offset=0):
    """Generate offsets: i.e value offset for each basis function
    relative to a physical element representation."""
    offsets = []

    # Refer to reference if gdim == tdim. This is a hack to support
    # more stuff (in particular restricted elements)
    gdim = ufl_element.cell().geometric_dimension()
    tdim = ufl_element.cell().topological_dimension()
    if (gdim == tdim):
        return _generate_reference_offsets(create_element(ufl_element))

    if isinstance(ufl_element, ufl.MixedElement):
        for e in ufl_element.sub_elements():
            offsets += _generate_physical_offsets(e, offset)
            offset += _value_size(e)
    elif isinstance(ufl_element, ufl.EnrichedElement):
        for e in ufl_element._elements:
            offsets += _generate_physical_offsets(e, offset)
    elif isinstance(ufl_element, ufl.FiniteElement):
        element = create_element(ufl_element)
        offsets = [offset]*element.space_dimension()
    else:
        raise NotImplementedError, \
            "This element combination is not implemented"
    return offsets
Exemplo n.º 6
0
def compute_integral_ir(itg_data, form_data, form_id, element_numbers,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing uflacs representation")

    # Initialise representation
    ir = initialize_integral_ir("uflacs", itg_data, form_data, form_id)

    # Sort integrals into a dict with quadrature degree and rule as key
    sorted_integrals = sort_integrals(itg_data.integrals,
                                      itg_data.metadata["quadrature_degree"],
                                      itg_data.metadata["quadrature_rule"])

    # TODO: Might want to create the uflacs ir first and then create the tables we need afterwards!
    # Tabulate quadrature points and basis function values in these points
    integrals_dict, psi_tables, quadrature_rules = \
        tabulate_basis(sorted_integrals, form_data, itg_data)

    # Store element numbers, needed for classnames
    ir["element_numbers"] = element_numbers

    # Delegate to flacs to build its intermediate representation and add to ir
    uflacs_ir = compute_uflacs_integral_ir(psi_tables, ir["entitytype"],
                                           integrals_dict, form_data,
                                           parameters)

    # Store uflacs generated part separately
    ir["uflacs"] = uflacs_ir

    # Create and save the optisation parameters # TODO: Define uflacs specific optimization parameters instead
    #ir["optimise_parameters"] = parse_optimise_parameters(parameters)

    # Save tables for quadrature weights and points
    ir["quadrature_rules"] = quadrature_rules

    # Create dimensions of primary indices, needed to reset the argument 'A'
    # given to tabulate_tensor() by the assembler.
    ir["prim_idims"] = [
        create_element(ufl_element).space_dimension()
        for ufl_element in form_data.argument_elements
    ]

    # Added for uflacs, not sure if this is the best way to get this:
    ir["coeff_idims"] = [
        create_element(ufl_element).space_dimension()
        for ufl_element in form_data.coefficient_elements
    ]

    return ir
def _compute_dofmap_ir(ufl_element, element_id, element_numbers):
    "Compute intermediate representation of dofmap."

    # Create FIAT element
    element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Precompute repeatedly used items
    num_dofs_per_entity = _num_dofs_per_entity(element)
    facet_dofs = _tabulate_facet_dofs(element, cell)

    # Store id
    ir = {"id": element_id}

    # Compute data for each function
    ir["signature"] = "FFC dofmap for " + repr(ufl_element)
    ir["needs_mesh_entities"] = _needs_mesh_entities(element)
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["global_dimension"] = _global_dimension(element)
    ir["local_dimension"] = element.space_dimension()
    ir["num_facet_dofs"] = len(facet_dofs[0])
    ir["num_entity_dofs"] = num_dofs_per_entity
    ir["tabulate_dofs"] = _tabulate_dofs(element, cell)
    ir["tabulate_facet_dofs"] = facet_dofs
    ir["tabulate_entity_dofs"] = (element.entity_dofs(), num_dofs_per_entity)
    ir["tabulate_coordinates"] = _tabulate_coordinates(ufl_element, element)
    ir["num_sub_dofmaps"] = ufl_element.num_sub_elements()
    ir["create_sub_dofmap"] = _create_sub_foo(ufl_element, element_numbers)

    #debug_ir(ir, "dofmap")

    return ir
def _compute_element_ir(ufl_element, element_id, element_numbers):
    "Compute intermediate representation of element."

    # Create FIAT element
    element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Store id
    ir = {"id": element_id}

    # Compute data for each function
    ir["signature"] = repr(ufl_element)
    ir["cell_shape"] = cell.cellname()
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["space_dimension"] = element.space_dimension()
    ir["value_rank"] = len(ufl_element.value_shape())
    ir["value_dimension"] = ufl_element.value_shape()
    ir["evaluate_basis"] = _evaluate_basis(ufl_element, element, cell)
    ir["evaluate_dof"] = _evaluate_dof(ufl_element, element, cell)
    ir["interpolate_vertex_values"] = _interpolate_vertex_values(ufl_element, element, cell)
    ir["num_sub_elements"] = ufl_element.num_sub_elements()
    ir["create_sub_element"] = _create_sub_foo(ufl_element, element_numbers)

    #debug_ir(ir, "finite_element")

    return ir
Exemplo n.º 9
0
def _generate_offsets(ufl_element, reference_offset=0, physical_offset=0):
    """Generate offsets: i.e value offset for each basis function
    relative to a physical element representation."""
    if isinstance(ufl_element, ufl.MixedElement):
        offsets = []
        for e in ufl_element.sub_elements():
            offsets += _generate_offsets(e, reference_offset, physical_offset)
            # e is a ufl element, so value_size means the physical value size
            reference_offset += e.reference_value_size()
            physical_offset += e.value_size()
        return offsets
    elif isinstance(ufl_element, ufl.EnrichedElement):
        offsets = []
        for e in ufl_element._elements:  # TODO: Avoid private member access
            offsets += _generate_offsets(e, reference_offset, physical_offset)
        return offsets
    elif isinstance(ufl_element, ufl.FiniteElement):
        fiat_element = create_element(ufl_element)
        return [(reference_offset, physical_offset)
                ] * fiat_element.space_dimension()
    else:
        # TODO: Support RestrictedElement, QuadratureElement,
        #       TensorProductElement, etc.!  and replace
        #       _generate_{physical|reference}_offsets with this
        #       function.
        raise NotImplementedError(
            "This element combination is not implemented")
Exemplo n.º 10
0
def _generate_offsets(ufl_element, reference_offset=0, physical_offset=0):
    """Generate offsets: i.e value offset for each basis function
    relative to a physical element representation."""

    if isinstance(ufl_element, ufl.MixedElement):
        offsets = []
        for e in ufl_element.sub_elements():
            offsets += _generate_offsets(e, reference_offset, physical_offset)
            # e is a ufl element, so value_size means the physical value size
            reference_offset += e.reference_value_size()
            physical_offset += e.value_size()
        return offsets

    elif isinstance(ufl_element, ufl.EnrichedElement):
        offsets = []
        for e in ufl_element._elements:  # TODO: Avoid private member access
            offsets += _generate_offsets(e, reference_offset, physical_offset)
        return offsets

    elif isinstance(ufl_element, ufl.FiniteElement):
        fiat_element = create_element(ufl_element)
        return [(reference_offset, physical_offset)] * fiat_element.space_dimension()

    else:
        # TODO: Support RestrictedElement, QuadratureElement,
        #       TensorProductElement, etc.!  and replace
        #       _generate_{physical|reference}_offsets with this
        #       function.
        raise NotImplementedError("This element combination is not implemented")
Exemplo n.º 11
0
Arquivo: access.py Projeto: FEniCS/ffc
    def cell_vertices(self, e, mt, tabledata, num_points):
        L = self.language

        # Get properties of domain
        domain = mt.terminal.ufl_domain()
        gdim = domain.geometric_dimension()
        coordinate_element = domain.ufl_coordinate_element()

        # Get dimension and dofmap of scalar element
        assert isinstance(coordinate_element, MixedElement)
        assert coordinate_element.value_shape() == (gdim,)
        ufl_scalar_element, = set(coordinate_element.sub_elements())
        assert ufl_scalar_element.family() in ("Lagrange", "Q", "S")
        fiat_scalar_element = create_element(ufl_scalar_element)
        vertex_scalar_dofs = fiat_scalar_element.entity_dofs()[0]
        num_scalar_dofs = fiat_scalar_element.space_dimension()

        # Get dof and component
        dof, = vertex_scalar_dofs[mt.component[0]]
        component = mt.component[1]

        expr = self.symbols.domain_dof_access(dof, component,
                                              gdim, num_scalar_dofs,
                                              mt.restriction)
        return expr
def _extract_element_data(element_map, element_numbers):
    "Extract element data for psi_tables"

    # Iterate over map
    element_data = {}
    for elements in six.itervalues(element_map):
        for ufl_element, counter in six.iteritems(elements):

            # Create corresponding FIAT element
            fiat_element = create_element(ufl_element)

            # Compute value size
            value_size = product(ufl_element.value_shape())

            # Get element number
            element_number = element_numbers.get(ufl_element)
            if element_number is None:
                # FIXME: Should not be necessary, we should always know the element number
                #warning("Missing element number, likely because vector elements are not yet supported in custom integrals.")
                pass

            # Store data
            element_data[counter] = {
                "value_size": value_size,
                "num_element_dofs": fiat_element.space_dimension(),
                "element_number": element_number
            }

    return element_data
def _init_table(arguments, domain_type, points, facet0, facet1):
    """Initialize table of basis functions and their derivatives at
    the given quadrature points for each element."""

    # Compute maximum number of derivatives for each element
    num_derivatives = {}
    for v in arguments:
        ufl_element = v.element
        order = len(v.derivatives)
        if ufl_element in num_derivatives:
            num_derivatives[ufl_element] = max(order, num_derivatives[ufl_element])
        else:
            num_derivatives[ufl_element] = order

    # Call FIAT to tabulate the basis functions for each element
    table = {}
    for (ufl_element, order) in num_derivatives.items():
        fiat_element = create_element(ufl_element)
        if domain_type == Measure.CELL:
            table[(ufl_element, None)] = fiat_element.tabulate(order, points)
        elif domain_type == Measure.EXTERIOR_FACET:
            x = map_facet_points(points, facet0)
            table[(ufl_element, None)] = fiat_element.tabulate(order, x)
        elif domain_type == Measure.INTERIOR_FACET:
            x0 = map_facet_points(points, facet0)
            x1 = map_facet_points(points, facet1)
            table[(ufl_element, "+")] = fiat_element.tabulate(order, x0)
            table[(ufl_element, "-")] = fiat_element.tabulate(order, x1)

    return table
Exemplo n.º 14
0
def _init_table(arguments, integral_type, points, facet0, facet1):
    """Initialize table of basis functions and their derivatives at
    the given quadrature points for each element."""

    # Compute maximum number of derivatives for each element
    num_derivatives = {}
    for v in arguments:
        ufl_element = v.element
        order = len(v.derivatives)
        if ufl_element in num_derivatives:
            num_derivatives[ufl_element] = max(order,
                                               num_derivatives[ufl_element])
        else:
            num_derivatives[ufl_element] = order

    # Call FIAT to tabulate the basis functions for each element
    table = {}
    for (ufl_element, order) in num_derivatives.items():
        fiat_element = create_element(ufl_element)
        if integral_type == Measure.CELL:
            table[(ufl_element, None)] = fiat_element.tabulate(order, points)
        elif integral_type == Measure.EXTERIOR_FACET:
            x = map_facet_points(points, facet0)
            table[(ufl_element, None)] = fiat_element.tabulate(order, x)
        elif integral_type == Measure.INTERIOR_FACET:
            x0 = map_facet_points(points, facet0)
            x1 = map_facet_points(points, facet1)
            table[(ufl_element, "+")] = fiat_element.tabulate(order, x0)
            table[(ufl_element, "-")] = fiat_element.tabulate(order, x1)

    return table
Exemplo n.º 15
0
def transform_component(component, offset, ufl_element):
    """
    This function accounts for the fact that if the geometrical and
    topological dimension does not match, then for native vector
    elements, in particular the Piola-mapped ones, the physical value
    dimensions and the reference value dimensions are not the
    same. This has certain consequences for mixed elements, aka 'fun
    with offsets'.
    """
    # This code is used for tensor/monomialtransformation.py and
    # quadrature/quadraturetransformerbase.py.

    cell = ufl_element.cell()
    gdim = cell.geometric_dimension()
    tdim = cell.topological_dimension()

    # Do nothing if we are not in a special case: The special cases
    # occur if we have piola mapped elements (for which value_shape !=
    # ()), and if gdim != tdim)
    if gdim == tdim:
        return component, offset
    all_mappings = create_element(ufl_element).mapping()
    special_case = (any(['piola' in m for m in all_mappings])
                    and ufl_element.num_sub_elements() > 1)
    if not special_case:
        return component, offset

    # Extract lists of reference and physical value dimensions by
    # sub-element
    reference_value_dims = []
    physical_value_dims = []
    for sub_element in ufl_element.sub_elements():
        assert (len(sub_element.value_shape()) < 2), \
            "Vector-valued assumption failed"
        if sub_element.value_shape() == ():
            reference_value_dims += [1]
            physical_value_dims += [1]
        else:
            reference_value_dims += [sub_element.value_shape()[0]
                                     - (gdim - tdim)]
            physical_value_dims += [sub_element.value_shape()[0]]

    # Figure out which sub-element number 'component' is in,
    # 'sub_element_number' contains the result
    tot = physical_value_dims[0]
    for sub_element_number in range(len(physical_value_dims)):
        if component < tot:
            break
        else:
            tot += physical_value_dims[sub_element_number + 1]

    # Compute the new reference offset:
    reference_offset = sum(reference_value_dims[:sub_element_number])
    physical_offset = sum(physical_value_dims[:sub_element_number])
    shift = physical_offset - reference_offset

    # Compute the component relative to the reference frame
    reference_component = component - shift

    return reference_component, reference_offset
Exemplo n.º 16
0
def transform_component(component, offset, ufl_element):
    """
    This function accounts for the fact that if the geometrical and
    topological dimension does not match, then for native vector
    elements, in particular the Piola-mapped ones, the physical value
    dimensions and the reference value dimensions are not the
    same. This has certain consequences for mixed elements, aka 'fun
    with offsets'.
    """
    # This code is used for tensor/monomialtransformation.py and
    # quadrature/quadraturetransformerbase.py.

    domain, = ufl_element.domains() # Assuming single domain
    gdim = domain.geometric_dimension()
    tdim = domain.topological_dimension()

    # Do nothing if we are not in a special case: The special cases
    # occur if we have piola mapped elements (for which value_shape !=
    # ()), and if gdim != tdim)
    if gdim == tdim:
        return component, offset
    all_mappings =  create_element(ufl_element).mapping()
    special_case = (any(['piola' in m for m in all_mappings])
                    and ufl_element.num_sub_elements() > 1)
    if not special_case:
        return component, offset

    # Extract lists of reference and physical value dimensions by
    # sub-element
    reference_value_dims = []
    physical_value_dims = []
    for sub_element in ufl_element.sub_elements():
        assert (len(sub_element.value_shape()) < 2), \
            "Vector-valued assumption failed"
        if sub_element.value_shape() == ():
            reference_value_dims += [1]
            physical_value_dims += [1]
        else:
            reference_value_dims += [sub_element.value_shape()[0]
                                     - (gdim - tdim)]
            physical_value_dims += [sub_element.value_shape()[0]]

    # Figure out which sub-element number 'component' is in,
    # 'sub_element_number' contains the result
    tot = physical_value_dims[0]
    for sub_element_number in range(len(physical_value_dims)):
        if component < tot:
            break
        else:
            tot += physical_value_dims[sub_element_number+1]

    # Compute the new reference offset:
    reference_offset = sum(reference_value_dims[:sub_element_number])
    physical_offset = sum(physical_value_dims[:sub_element_number])
    shift = physical_offset - reference_offset

    # Compute the component relative to the reference frame
    reference_component = component - shift

    return reference_component, reference_offset
Exemplo n.º 17
0
def _compute_element_ir(ufl_element, element_id, element_numbers):
    "Compute intermediate representation of element."

    # Create FIAT element
    element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Store id
    ir = {"id": element_id}

    # Compute data for each function
    ir["signature"] = repr(ufl_element)
    ir["cell_shape"] = cell.cellname()
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["space_dimension"] = element.space_dimension()
    ir["value_rank"] = len(ufl_element.value_shape())
    ir["value_dimension"] = ufl_element.value_shape()
    ir["evaluate_basis"] = _evaluate_basis(ufl_element, element, cell)
    ir["evaluate_dof"] = _evaluate_dof(ufl_element, element, cell)
    ir["interpolate_vertex_values"] = _interpolate_vertex_values(
        ufl_element, element, cell)
    ir["num_sub_elements"] = ufl_element.num_sub_elements()
    ir["create_sub_element"] = _create_sub_foo(ufl_element, element_numbers)

    #debug_ir(ir, "finite_element")

    return ir
Exemplo n.º 18
0
def _compute_dofmap_ir(ufl_element, element_id, element_numbers):
    "Compute intermediate representation of dofmap."

    # Create FIAT element
    element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Precompute repeatedly used items
    num_dofs_per_entity = _num_dofs_per_entity(element)
    facet_dofs = _tabulate_facet_dofs(element, cell)

    # Store id
    ir = {"id": element_id}

    # Compute data for each function
    ir["signature"] = "FFC dofmap for " + repr(ufl_element)
    ir["needs_mesh_entities"] = _needs_mesh_entities(element)
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["global_dimension"] = _global_dimension(element)
    ir["local_dimension"] = element.space_dimension()
    ir["num_facet_dofs"] = len(facet_dofs[0])
    ir["num_entity_dofs"] = num_dofs_per_entity
    ir["tabulate_dofs"] = _tabulate_dofs(element, cell)
    ir["tabulate_facet_dofs"] = facet_dofs
    ir["tabulate_entity_dofs"] = (element.entity_dofs(), num_dofs_per_entity)
    ir["tabulate_coordinates"] = _tabulate_coordinates(ufl_element, element)
    ir["num_sub_dofmaps"] = ufl_element.num_sub_elements()
    ir["create_sub_dofmap"] = _create_sub_foo(ufl_element, element_numbers)

    #debug_ir(ir, "dofmap")

    return ir
Exemplo n.º 19
0
def _extract_element_data(element_map, element_numbers):
    "Extract element data for psi_tables"

    # Iterate over map
    element_data = {}
    for elements in six.itervalues(element_map):
        for ufl_element, counter in six.iteritems(elements):

            # Create corresponding FIAT element
            fiat_element = create_element(ufl_element)

            # Compute value size
            value_size = product(ufl_element.value_shape())

            # Get element number
            element_number = element_numbers.get(ufl_element)
            if element_number is None:
                # FIXME: Should not be necessary, we should always know the element number
                #warning("Missing element number, likely because vector elements are not yet supported in custom integrals.")
                pass

            # Store data
            element_data[counter] = {"value_size":      value_size,
                                     "num_element_dofs": fiat_element.space_dimension(),
                                     "element_number":  element_number}

    return element_data
Exemplo n.º 20
0
def _compute_element_ir(ufl_element, element_numbers, classnames, parameters):
    """Compute intermediate representation of element."""
    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()
    cellname = cell.cellname()

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = classnames["finite_element"][ufl_element]

    # Compute data for each function
    ir["signature"] = repr(ufl_element)
    ir["cell_shape"] = cellname
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["space_dimension"] = fiat_element.space_dimension()
    ir["value_shape"] = ufl_element.value_shape()
    ir["reference_value_shape"] = ufl_element.reference_value_shape()

    ir["degree"] = ufl_element.degree()
    ir["family"] = ufl_element.family()

    ir["evaluate_basis"] = _evaluate_basis(ufl_element, fiat_element,
                                           parameters["epsilon"])
    ir["evaluate_dof"] = _evaluate_dof(ufl_element, fiat_element)
    ir["tabulate_dof_coordinates"] = _tabulate_dof_coordinates(
        ufl_element, fiat_element)
    ir["num_sub_elements"] = ufl_element.num_sub_elements()
    ir["create_sub_element"] = [
        classnames["finite_element"][e] for e in ufl_element.sub_elements()
    ]

    return ir_element(**ir)
Exemplo n.º 21
0
def _compute_dofmap_ir(ufl_element, element_numbers, classnames, parameters):
    """Compute intermediate representation of dofmap."""
    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Precompute repeatedly used items
    num_dofs_per_entity = _num_dofs_per_entity(fiat_element)
    entity_dofs = fiat_element.entity_dofs()

    edge_permutations, face_permutations, cell_topology = _compute_dofmap_permutation_tables(
        fiat_element, cell)

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = classnames["dofmap"][ufl_element]

    # Compute data for each function
    ir["signature"] = "FFC dofmap for " + repr(ufl_element)
    ir["num_global_support_dofs"] = _num_global_support_dofs(fiat_element)
    ir["num_element_support_dofs"] = fiat_element.space_dimension(
    ) - ir["num_global_support_dofs"]
    ir["num_entity_dofs"] = num_dofs_per_entity
    ir["tabulate_entity_dofs"] = (entity_dofs, num_dofs_per_entity)
    ir["num_sub_dofmaps"] = ufl_element.num_sub_elements()
    ir["create_sub_dofmap"] = [
        classnames["dofmap"][e] for e in ufl_element.sub_elements()
    ]

    return ir_dofmap(**ir)
Exemplo n.º 22
0
def compute_integral_ir(itg_data,
                        form_data,
                        form_id,
                        element_numbers,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing uflacs representation")

    # Initialise representation
    ir = initialize_integral_ir("uflacs", itg_data, form_data, form_id)

    # Sort integrals into a dict with quadrature degree and rule as key
    sorted_integrals = sort_integrals(itg_data.integrals,
                                      itg_data.metadata["quadrature_degree"],
                                      itg_data.metadata["quadrature_rule"])

    # TODO: Might want to create the uflacs ir first and then create the tables we need afterwards!
    # Tabulate quadrature points and basis function values in these points
    integrals_dict, psi_tables, quadrature_rules = \
        tabulate_basis(sorted_integrals, form_data, itg_data)

    # Store element numbers, needed for classnames
    ir["element_numbers"] = element_numbers

    # Delegate to flacs to build its intermediate representation and add to ir
    uflacs_ir = compute_uflacs_integral_ir(psi_tables, ir["entitytype"], integrals_dict, form_data, parameters)

    # Store uflacs generated part separately
    ir["uflacs"] = uflacs_ir

    # Create and save the optisation parameters # TODO: Define uflacs specific optimization parameters instead
    #ir["optimise_parameters"] = parse_optimise_parameters(parameters)

    # Save tables for quadrature weights and points
    ir["quadrature_rules"] = quadrature_rules

    # Create dimensions of primary indices, needed to reset the argument 'A'
    # given to tabulate_tensor() by the assembler.
    ir["prim_idims"] = [create_element(ufl_element).space_dimension()
                        for ufl_element in form_data.argument_elements]

    # Added for uflacs, not sure if this is the best way to get this:
    ir["coeff_idims"] = [create_element(ufl_element).space_dimension()
                         for ufl_element in form_data.coefficient_elements]

    return ir
Exemplo n.º 23
0
def needs_oriented_jacobian(form_data):
    # Check whether this form needs an oriented jacobian (only forms
    # involgin contravariant piola mappings seem to need it)
    for ufl_element in form_data.unique_elements:
        element = create_element(ufl_element)
        if "contravariant piola" in element.mapping():
            return True
    return False
def needs_oriented_jacobian(form_data):
    # Check whether this form needs an oriented jacobian (only forms
    # involgin contravariant piola mappings seem to need it)
    for ufl_element in form_data.unique_elements:
        element = create_element(ufl_element)
        if "contravariant piola" in element.mapping():
            return True
    return False
def compute_integral_ir(itg_data,
                        form_data,
                        form_id,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing quadrature representation")

    # Initialise representation
    ir = initialize_integral_ir("quadrature", itg_data, form_data, form_id)

    # Sort integrals into a dict with number of integral points as key
    sorted_integrals = _sort_integrals(itg_data.integrals, itg_data.metadata, form_data)

    # Tabulate quadrature points and basis function values in these points
    integrals_dict, psi_tables, quad_weights = \
        _tabulate_basis(sorted_integrals, itg_data.domain_type, form_data)

    # Save tables for quadrature weights and points
    ir["quadrature_weights"]  = quad_weights

    # Create dimensions of primary indices, needed to reset the argument 'A'
    # given to tabulate_tensor() by the assembler.
    ir["prim_idims"] = [create_element(ufl_element).space_dimension()
                        for ufl_element in form_data.argument_elements]

    # Create and save the optisation parameters.
    ir["optimise_parameters"] = _parse_optimise_parameters(parameters)

    # Create transformer.
    if ir["optimise_parameters"]["optimisation"]:
        QuadratureTransformerClass = QuadratureTransformerOpt
    else:
        QuadratureTransformerClass = QuadratureTransformer
    transformer = QuadratureTransformerClass(psi_tables,
                                             quad_weights,
                                             form_data.geometric_dimension,
                                             form_data.topological_dimension,
                                             ir["entitytype"],
                                             form_data.function_replace_map,
                                             ir["optimise_parameters"])

    # Transform integrals.
    ir["trans_integrals"] = _transform_integrals_by_type(ir, transformer, integrals_dict,
                                                         itg_data.domain_type, form_data.cell)

    # Save tables populated by transformer
    ir["name_map"] = transformer.name_map
    ir["unique_tables"] = transformer.unique_tables  # Basis values?

    # Save tables map, to extract table names for optimisation option -O.
    ir["psi_tables_map"] = transformer.psi_tables_map
    ir["additional_includes_set"] = transformer.additional_includes_set

    # Insert empty data which will be populated if optimization is turned on
    ir["geo_consts"] = {}

    return ir
Exemplo n.º 26
0
def compute_integral_ir(itg_data, form_data, form_id, parameters):
    "Compute intermediate represention of integral."

    info("Computing uflacs representation")

    # Initialise representation
    ir = initialize_integral_ir("uflacs", itg_data, form_data, form_id)

    # Sort integrals into a dict with number of integral points as key
    sorted_integrals = _sort_integrals(itg_data.integrals, itg_data.metadata,
                                       form_data)

    # Tabulate quadrature points and basis function values in these points
    integrals_dict, psi_tables, quad_weights = \
        _tabulate_basis(sorted_integrals, itg_data.domain_type, form_data)

    # Save tables for quadrature weights and points
    ir["quadrature_weights"] = quad_weights

    # Save tables for basis function values
    ir["psi_tables"] = psi_tables

    # Create dimensions of primary indices, needed to reset the argument 'A'
    # given to tabulate_tensor() by the assembler.
    ir["prim_idims"] = [
        create_element(ufl_element).space_dimension()
        for ufl_element in form_data.argument_elements
    ]

    # Added for uflacs, not sure if this is the best way to get this:
    ir["coeff_idims"] = [
        create_element(ufl_element).space_dimension()
        for ufl_element in form_data.coefficient_elements
    ]

    # Create and save the optisation parameters.
    ir["optimise_parameters"] = _parse_optimise_parameters(parameters)

    # Delegate to flacs to build its intermediate representation and add to ir
    import uflacs.backends.ffc
    uir = uflacs.backends.ffc.compute_tabulate_tensor_ir(
        ir, integrals_dict, form_data, parameters)
    ir.update(uir)

    return ir
Exemplo n.º 27
0
def compute_integral_ir(itg_data, form_data, form_id, parameters):
    "Compute intermediate represention of integral."

    info("Computing quadrature representation")

    # Initialise representation
    ir = initialize_integral_ir("quadrature", itg_data, form_data, form_id)

    # Sort integrals into a dict with number of integral points as key
    sorted_integrals = _sort_integrals(itg_data.integrals, itg_data.metadata,
                                       form_data)

    # Tabulate quadrature points and basis function values in these points
    integrals_dict, psi_tables, quad_weights = \
        _tabulate_basis(sorted_integrals, itg_data.domain_type, form_data)

    # Save tables for quadrature weights and points
    ir["quadrature_weights"] = quad_weights

    # Create dimensions of primary indices, needed to reset the argument 'A'
    # given to tabulate_tensor() by the assembler.
    ir["prim_idims"] = [
        create_element(ufl_element).space_dimension()
        for ufl_element in form_data.argument_elements
    ]

    # Create and save the optisation parameters.
    ir["optimise_parameters"] = _parse_optimise_parameters(parameters)

    # Create transformer.
    if ir["optimise_parameters"]["optimisation"]:
        QuadratureTransformerClass = QuadratureTransformerOpt
    else:
        QuadratureTransformerClass = QuadratureTransformer
    transformer = QuadratureTransformerClass(psi_tables, quad_weights,
                                             form_data.geometric_dimension,
                                             form_data.topological_dimension,
                                             ir["entitytype"],
                                             form_data.function_replace_map,
                                             ir["optimise_parameters"])

    # Transform integrals.
    ir["trans_integrals"] = _transform_integrals_by_type(
        ir, transformer, integrals_dict, itg_data.domain_type, form_data.cell)

    # Save tables populated by transformer
    ir["name_map"] = transformer.name_map
    ir["unique_tables"] = transformer.unique_tables  # Basis values?

    # Save tables map, to extract table names for optimisation option -O.
    ir["psi_tables_map"] = transformer.psi_tables_map
    ir["additional_includes_set"] = transformer.additional_includes_set

    # Insert empty data which will be populated if optimization is turned on
    ir["geo_consts"] = {}

    return ir
    def _get_auxiliary_variables(self,
                                 ufl_function,
                                 component,
                                 derivatives):
        "Helper function for both Coefficient and Argument."

        # Get UFL element.
        ufl_element = ufl_function.element()

        # Get subelement and the relative (flattened) component (in case we have mixed elements).
        local_comp, local_elem = ufl_element.extract_component(component)
        ffc_assert(len(local_comp) <= 1, "Assuming there are no tensor-valued basic elements.")
        local_comp = local_comp[0] if local_comp else 0

        # Check that component != not () since the UFL component map will turn
        # it into 0, and () does not mean zeroth component in this context.
        if len(component):
            # Map component using component map from UFL. (TODO: inefficient use of this function)
            comp_map, comp_num = build_component_numbering(ufl_element.value_shape(), ufl_element.symmetry())
            component = comp_map[component]

            # Map physical components into reference components
            component, dummy = transform_component(component, 0, ufl_element)

            # Compute the local offset (needed for non-affine mappings).
            local_offset = component - local_comp
        else:
            # Compute the local offset (needed for non-affine mappings).
            local_offset = 0

        # Create FFC element.
        ffc_element = create_element(ufl_element)

        # Assuming that mappings for all basisfunctions are equal
        # (they should be).
        ffc_sub_element = create_element(local_elem)
        transformation = ffc_sub_element.mapping()[0]

        # Generate FFC multi index for derivatives.
        multiindices = FFCMultiIndex([range(self.tdim)]*len(derivatives)).indices

        #print "in create_auxiliary"
        #print "component = ", component
        return (component, local_elem, local_comp, local_offset, ffc_element, transformation, multiindices)
Exemplo n.º 29
0
def num_coordinate_component_dofs(coordinate_element):
    """Get the number of dofs for a coordinate component for this degree.

    """
    fiat_elements = create_element(coordinate_element).elements()
    # Extracting only first component degrees of freedom from FIAT
    fiat_element = fiat_elements[0]
    assert (all(
        isinstance(element, type(fiat_element)) for element in fiat_elements))
    return fiat_element.space_dimension()
Exemplo n.º 30
0
def numBasisFunctions(e):
    """Return the number of basis functions. e can be a form or an element -
    if e is a form, the element from the test function is used."""
    if isinstance(e, FormData):
        # Use the element from the first argument, which should be the TestFunction
        e = e.arguments[0].element()
    element = create_element(e)
    if isinstance(element, FFCMixedElement):
        return len(element.entity_dofs()) * element.num_components()
    else:
        return element.get_nodal_basis().get_num_members()
Exemplo n.º 31
0
def _compute_dofmap_ir(ufl_element,
                       element_numbers,
                       classnames,
                       parameters,
                       jit=False):
    "Compute intermediate representation of dofmap."

    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Precompute repeatedly used items
    num_dofs_per_entity = _num_dofs_per_entity(fiat_element)
    entity_dofs = fiat_element.entity_dofs()
    facet_dofs = _tabulate_facet_dofs(fiat_element, cell)
    entity_closure_dofs, num_dofs_per_entity_closure = \
        _tabulate_entity_closure_dofs(fiat_element, cell)

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = classnames["dofmap"][ufl_element]

    # Remember jit status
    ir["jit"] = jit

    # Compute data for each function
    ir["signature"] = "FFC dofmap for " + repr(ufl_element)
    ir["needs_mesh_entities"] = _needs_mesh_entities(fiat_element)
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["global_dimension"] = _global_dimension(fiat_element)
    ir["num_global_support_dofs"] = _num_global_support_dofs(fiat_element)
    ir["num_element_support_dofs"] = fiat_element.space_dimension(
    ) - ir["num_global_support_dofs"]
    ir["num_element_dofs"] = fiat_element.space_dimension()
    ir["num_facet_dofs"] = len(facet_dofs[0])
    ir["num_entity_dofs"] = num_dofs_per_entity
    ir["num_entity_closure_dofs"] = num_dofs_per_entity_closure
    ir["tabulate_dofs"] = _tabulate_dofs(fiat_element, cell)
    ir["tabulate_facet_dofs"] = facet_dofs
    ir["tabulate_entity_dofs"] = (entity_dofs, num_dofs_per_entity)
    ir["tabulate_entity_closure_dofs"] = (entity_closure_dofs, entity_dofs,
                                          num_dofs_per_entity)
    ir["num_sub_dofmaps"] = ufl_element.num_sub_elements()
    ir["create_sub_dofmap"] = [
        classnames["dofmap"][e] for e in ufl_element.sub_elements()
    ]

    return ir
Exemplo n.º 32
0
    def test_values(self, family, cell, degree, reference):
        # Create element
        element = create_element(FiniteElement(family, cell, degree))

        # Get some points and check basis function values at points
        points = [random_point(element_coords(cell)) for i in range(5)]
        for x in points:
            table = element.tabulate(0, (x,))
            basis = table[list(table.keys())[0]]
            for i in range(len(basis)):
                if not element.value_shape():
                    assert round(float(basis[i]) - reference[i](x), 10) == 0.0
                else:
                    for k in range(element.value_shape()[0]):
                        assert round(basis[i][k][0] - reference[i](x)[k] , 10) == 0.0
Exemplo n.º 33
0
    def test_values(self, family, cell, degree, reference):
        # Create element
        element = create_element(FiniteElement(family, cell, degree))

        # Get some points and check basis function values at points
        points = [random_point(element_coords(cell)) for i in range(5)]
        for x in points:
            table = element.tabulate(0, (x, ))
            basis = table[list(table.keys())[0]]
            for i in range(len(basis)):
                if not element.value_shape():
                    assert round(float(basis[i]) - reference[i](x), 10) == 0.0
                else:
                    for k in range(element.value_shape()[0]):
                        assert round(basis[i][k][0] - reference[i](x)[k],
                                     10) == 0.0
Exemplo n.º 34
0
    def facet_edge_vectors(self, e, mt, tabledata, num_points):
        L = self.language

        # Get properties of domain
        domain = mt.terminal.ufl_domain()
        cellname = domain.ufl_cell().cellname()
        gdim = domain.geometric_dimension()
        coordinate_element = domain.ufl_coordinate_element()

        if cellname in ("tetrahedron", "hexahedron"):
            pass
        elif cellname in ("interval", "triangle", "quadrilateral"):
            error(
                "The physical facet edge vectors doesn't make sense for {0} cell."
                .format(cellname))
        else:
            error("Unhandled cell types {0}.".format(cellname))

        # Get dimension and dofmap of scalar element
        assert isinstance(coordinate_element, MixedElement)
        assert coordinate_element.value_shape() == (gdim, )
        ufl_scalar_element, = set(coordinate_element.sub_elements())
        assert ufl_scalar_element.family() in ("Lagrange", "Q", "S")
        fiat_scalar_element = create_element(ufl_scalar_element)
        vertex_scalar_dofs = fiat_scalar_element.entity_dofs()[0]
        num_scalar_dofs = fiat_scalar_element.space_dimension()

        # Get edge vertices
        facet = self.symbols.entity("facet", mt.restriction)
        facet_edge = mt.component[0]
        facet_edge_vertices = L.Symbol(
            "{0}_facet_edge_vertices".format(cellname))
        vertex0 = facet_edge_vertices[facet][facet_edge][0]
        vertex1 = facet_edge_vertices[facet][facet_edge][1]

        # Get dofs and component
        component = mt.component[1]
        assert coordinate_element.degree() == 1, "Assuming degree 1 element"
        dof0 = vertex0
        dof1 = vertex1

        expr = (self.symbols.domain_dof_access(
            dof0, component, gdim, num_scalar_dofs, mt.restriction) -
                self.symbols.domain_dof_access(
                    dof1, component, gdim, num_scalar_dofs, mt.restriction))
        return expr
Exemplo n.º 35
0
Arquivo: access.py Projeto: FEniCS/ffc
    def facet_edge_vectors(self, e, mt, tabledata, num_points):
        L = self.language

        # Get properties of domain
        domain = mt.terminal.ufl_domain()
        cellname = domain.ufl_cell().cellname()
        gdim = domain.geometric_dimension()
        coordinate_element = domain.ufl_coordinate_element()

        if cellname in ("tetrahedron", "hexahedron"):
            pass
        elif cellname in ("interval", "triangle", "quadrilateral"):
            error("The physical facet edge vectors doesn't make sense for {0} cell.".format(cellname))
        else:
            error("Unhandled cell types {0}.".format(cellname))

        # Get dimension and dofmap of scalar element
        assert isinstance(coordinate_element, MixedElement)
        assert coordinate_element.value_shape() == (gdim,)
        ufl_scalar_element, = set(coordinate_element.sub_elements())
        assert ufl_scalar_element.family() in ("Lagrange", "Q", "S")
        fiat_scalar_element = create_element(ufl_scalar_element)
        vertex_scalar_dofs = fiat_scalar_element.entity_dofs()[0]
        num_scalar_dofs = fiat_scalar_element.space_dimension()

        # Get edge vertices
        facet = self.symbols.entity("facet", mt.restriction)
        facet_edge = mt.component[0]
        facet_edge_vertices = L.Symbol("{0}_facet_edge_vertices".format(cellname))
        vertex0 = facet_edge_vertices[facet][facet_edge][0]
        vertex1 = facet_edge_vertices[facet][facet_edge][1]

        # Get dofs and component
        component = mt.component[1]
        assert coordinate_element.degree() == 1, "Assuming degree 1 element"
        dof0 = vertex0
        dof1 = vertex1

        expr = (
            self.symbols.domain_dof_access(dof0, component, gdim, num_scalar_dofs,
                                           mt.restriction)
          - self.symbols.domain_dof_access(dof1, component, gdim, num_scalar_dofs,
                                           mt.restriction)
        )
        return expr
Exemplo n.º 36
0
    def cell_edge_vectors(self, e, mt, tabledata, num_points):
        L = self.language

        # Get properties of domain
        domain = mt.terminal.ufl_domain()
        cellname = domain.ufl_cell().cellname()
        gdim = domain.geometric_dimension()
        coordinate_element = domain.ufl_coordinate_element()

        if cellname in ("triangle", "tetrahedron", "quadrilateral",
                        "hexahedron"):
            pass
        elif cellname == "interval":
            error(
                "The physical cell edge vectors doesn't make sense for interval cell."
            )
        else:
            error("Unhandled cell types {0}.".format(cellname))

        # Get dimension and dofmap of scalar element
        assert isinstance(coordinate_element, MixedElement)
        assert coordinate_element.value_shape() == (gdim, )
        ufl_scalar_element, = set(coordinate_element.sub_elements())
        assert ufl_scalar_element.family() in ("Lagrange", "Q", "S")
        fiat_scalar_element = create_element(ufl_scalar_element)
        vertex_scalar_dofs = fiat_scalar_element.entity_dofs()[0]
        num_scalar_dofs = fiat_scalar_element.space_dimension()

        # Get edge vertices
        edge = mt.component[0]
        edge_vertices = fiat_scalar_element.get_reference_element(
        ).get_topology()[1][edge]
        vertex0, vertex1 = edge_vertices

        # Get dofs and component
        dof0, = vertex_scalar_dofs[vertex0]
        dof1, = vertex_scalar_dofs[vertex1]
        component = mt.component[1]

        expr = (self.symbols.domain_dof_access(
            dof0, component, gdim, num_scalar_dofs, mt.restriction) -
                self.symbols.domain_dof_access(
                    dof1, component, gdim, num_scalar_dofs, mt.restriction))
        return expr
Exemplo n.º 37
0
def _compute_dofmap_ir(ufl_element, element_numbers, classnames, parameters, jit=False):
    "Compute intermediate representation of dofmap."

    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()

    # Precompute repeatedly used items
    num_dofs_per_entity = _num_dofs_per_entity(fiat_element)
    entity_dofs = fiat_element.entity_dofs()
    facet_dofs = _tabulate_facet_dofs(fiat_element, cell)
    entity_closure_dofs, num_dofs_per_entity_closure = \
        _tabulate_entity_closure_dofs(fiat_element, cell)

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = classnames["dofmap"][ufl_element]

    # Remember jit status
    ir["jit"] = jit

    # Compute data for each function
    ir["signature"] = "FFC dofmap for " + repr(ufl_element)
    ir["needs_mesh_entities"] = _needs_mesh_entities(fiat_element)
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["global_dimension"] = _global_dimension(fiat_element)
    ir["num_global_support_dofs"] = _num_global_support_dofs(fiat_element)
    ir["num_element_support_dofs"] = fiat_element.space_dimension() - ir["num_global_support_dofs"]
    ir["num_element_dofs"] = fiat_element.space_dimension()
    ir["num_facet_dofs"] = len(facet_dofs[0])
    ir["num_entity_dofs"] = num_dofs_per_entity
    ir["num_entity_closure_dofs"] = num_dofs_per_entity_closure
    ir["tabulate_dofs"] = _tabulate_dofs(fiat_element, cell)
    ir["tabulate_facet_dofs"] = facet_dofs
    ir["tabulate_entity_dofs"] = (entity_dofs, num_dofs_per_entity)
    ir["tabulate_entity_closure_dofs"] = (entity_closure_dofs, entity_dofs, num_dofs_per_entity)
    ir["num_sub_dofmaps"] = ufl_element.num_sub_elements()
    ir["create_sub_dofmap"] = [classnames["dofmap"][e]
                               for e in ufl_element.sub_elements()]

    return ir
Exemplo n.º 38
0
Arquivo: access.py Projeto: FEniCS/ffc
    def cell_edge_vectors(self, e, mt, tabledata, num_points):
        L = self.language

        # Get properties of domain
        domain = mt.terminal.ufl_domain()
        cellname = domain.ufl_cell().cellname()
        gdim = domain.geometric_dimension()
        coordinate_element = domain.ufl_coordinate_element()

        if cellname in ("triangle", "tetrahedron", "quadrilateral", "hexahedron"):
            pass
        elif cellname == "interval":
            error("The physical cell edge vectors doesn't make sense for interval cell.")
        else:
            error("Unhandled cell types {0}.".format(cellname))

        # Get dimension and dofmap of scalar element
        assert isinstance(coordinate_element, MixedElement)
        assert coordinate_element.value_shape() == (gdim,)
        ufl_scalar_element, = set(coordinate_element.sub_elements())
        assert ufl_scalar_element.family() in ("Lagrange", "Q", "S")
        fiat_scalar_element = create_element(ufl_scalar_element)
        vertex_scalar_dofs = fiat_scalar_element.entity_dofs()[0]
        num_scalar_dofs = fiat_scalar_element.space_dimension()

        # Get edge vertices
        edge = mt.component[0]
        edge_vertices = fiat_scalar_element.get_reference_element().get_topology()[1][edge]
        vertex0, vertex1 = edge_vertices

        # Get dofs and component
        dof0, = vertex_scalar_dofs[vertex0]
        dof1, = vertex_scalar_dofs[vertex1]
        component = mt.component[1]

        expr = (
            self.symbols.domain_dof_access(dof0, component, gdim, num_scalar_dofs,
                                           mt.restriction)
          - self.symbols.domain_dof_access(dof1, component, gdim, num_scalar_dofs,
                                           mt.restriction)
        )
        return expr
Exemplo n.º 39
0
    def cell_vertices(self, e, mt, tabledata, num_points):
        # Get properties of domain
        domain = mt.terminal.ufl_domain()
        gdim = domain.geometric_dimension()
        coordinate_element = domain.ufl_coordinate_element()

        # Get dimension and dofmap of scalar element
        assert isinstance(coordinate_element, MixedElement)
        assert coordinate_element.value_shape() == (gdim, )
        ufl_scalar_element, = set(coordinate_element.sub_elements())
        assert ufl_scalar_element.family() in ("Lagrange", "Q", "S")
        fiat_scalar_element = create_element(ufl_scalar_element)
        vertex_scalar_dofs = fiat_scalar_element.entity_dofs()[0]
        num_scalar_dofs = fiat_scalar_element.space_dimension()

        # Get dof and component
        dof, = vertex_scalar_dofs[mt.component[0]]
        component = mt.component[1]

        expr = self.symbols.domain_dof_access(dof, component, gdim, num_scalar_dofs, mt.restriction)
        return expr
Exemplo n.º 40
0
def _compute_element_ir(ufl_element, element_numbers, classnames, parameters, jit):
    "Compute intermediate representation of element."

    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()
    cellname = cell.cellname()

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = classnames["finite_element"][ufl_element]

    # Remember jit status
    ir["jit"] = jit

    # Compute data for each function
    ir["signature"] = repr(ufl_element)
    ir["cell_shape"] = cellname
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["space_dimension"] = fiat_element.space_dimension()
    ir["value_shape"] = ufl_element.value_shape()
    ir["reference_value_shape"] = ufl_element.reference_value_shape()

    ir["degree"] = ufl_element.degree()
    ir["family"] = ufl_element.family()

    ir["evaluate_basis"] = _evaluate_basis(ufl_element, fiat_element, parameters["epsilon"])
    ir["evaluate_dof"] = _evaluate_dof(ufl_element, fiat_element)
    ir["interpolate_vertex_values"] = _interpolate_vertex_values(ufl_element,
                                                                 fiat_element)
    ir["tabulate_dof_coordinates"] = _tabulate_dof_coordinates(ufl_element,
                                                               fiat_element)
    ir["num_sub_elements"] = ufl_element.num_sub_elements()
    ir["create_sub_element"] = [classnames["finite_element"][e]
                                for e in ufl_element.sub_elements()]

    # debug_ir(ir, "finite_element")

    return ir
Exemplo n.º 41
0
def _compute_element_ir(ufl_element, prefix, element_numbers):
    "Compute intermediate representation of element."

    # This hits unimplemented FIAT functionality for OPEs; the IR
    # is only required for function evaluation at a point, not integrals
    if isinstance(ufl_element.cell(), ufl.OuterProductCell):
        return None
    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()
    cellname = cell.cellname()

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = make_classname(prefix, "finite_element", element_numbers[ufl_element])

    # Compute data for each function
    ir["cell"] = cell
    ir["signature"] = repr(ufl_element)
    ir["cell_shape"] = cellname
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["space_dimension"] = fiat_element.space_dimension()
    ir["value_rank"] = len(ufl_element.value_shape())
    ir["value_dimension"] = ufl_element.value_shape()
    ir["reference_value_dimension"] = ufl_element.reference_value_shape()
    ir["evaluate_basis"] = _evaluate_basis(ufl_element, fiat_element)
    ir["evaluate_dof"] = _evaluate_dof(ufl_element, fiat_element)
    ir["interpolate_vertex_values"] = _interpolate_vertex_values(ufl_element,
                                                                 fiat_element)
    ir["tabulate_dof_coordinates"] = _tabulate_dof_coordinates(ufl_element,
                                                               fiat_element)
    ir["num_sub_elements"] = ufl_element.num_sub_elements()
    ir["create_sub_element"] = [make_classname(prefix, "finite_element", element_numbers[e])
                                for e in ufl_element.sub_elements()]

    #debug_ir(ir, "finite_element")

    return ir
Exemplo n.º 42
0
def _compute_dofmap_ir(ufl_element, prefix, element_numbers):
    "Compute intermediate representation of dofmap."

    # This hits unimplemented FIAT functionality for OPEs; our
    # dofmaps are not produced by FFC anyway, AFAIK
    if isinstance(ufl_element.cell(), ufl.OuterProductCell):
        return None
    # Create FIAT element
    fiat_element = create_element(ufl_element)
    cell = ufl_element.cell()
    cellname = cell.cellname()

    # Precompute repeatedly used items
    num_dofs_per_entity = _num_dofs_per_entity(fiat_element)
    facet_dofs = _tabulate_facet_dofs(fiat_element, cell)

    # Store id
    ir = {"id": element_numbers[ufl_element]}
    ir["classname"] = make_classname(prefix, "dofmap", element_numbers[ufl_element])

    # Compute data for each function
    ir["signature"] = "FFC dofmap for " + repr(ufl_element)
    ir["needs_mesh_entities"] = _needs_mesh_entities(fiat_element)
    ir["cell"] = cell
    ir["topological_dimension"] = cell.topological_dimension()
    ir["geometric_dimension"] = cell.geometric_dimension()
    ir["global_dimension"] = _global_dimension(fiat_element)
    ir["num_element_dofs"] = fiat_element.space_dimension()
    ir["num_facet_dofs"] = len(facet_dofs[0])
    ir["num_entity_dofs"] = num_dofs_per_entity
    ir["tabulate_dofs"] = _tabulate_dofs(fiat_element, cell)
    ir["tabulate_facet_dofs"] = facet_dofs
    ir["tabulate_entity_dofs"] = (fiat_element.entity_dofs(), num_dofs_per_entity)
    ir["num_sub_dofmaps"] = ufl_element.num_sub_elements()
    ir["create_sub_dofmap"] = [make_classname(prefix, "dofmap", element_numbers[e])
                               for e in ufl_element.sub_elements()]

    return ir
Exemplo n.º 43
0
def _tabulate_coordinate_mapping_basis(ufl_element):
    # TODO: Move this function to a table generation module?

    # Get scalar element, assuming coordinates are represented
    # with a VectorElement of scalar subelements
    selement = ufl_element.sub_elements()[0]

    fiat_element = create_element(selement)
    cell = selement.cell()
    tdim = cell.topological_dimension()

    tables = {}

    # Get points
    origo = (0.0, ) * tdim
    midpoint = cell_midpoint(cell)

    # Tabulate basis
    t0 = fiat_element.tabulate(1, [origo])
    tm = fiat_element.tabulate(1, [midpoint])

    # Get basis values at cell origo
    tables["x0"] = t0[(0, ) * tdim][:, 0]

    # Get basis values at cell midpoint
    tables["xm"] = tm[(0, ) * tdim][:, 0]

    # Single direction derivatives, e.g. [(1,0), (0,1)] in 2d
    derivatives = [(0, ) * i + (1, ) + (0, ) * (tdim - 1 - i)
                   for i in range(tdim)]

    # Get basis derivative values at cell origo
    tables["J0"] = numpy.asarray([t0[d][:, 0] for d in derivatives])

    # Get basis derivative values at cell midpoint
    tables["Jm"] = numpy.asarray([tm[d][:, 0] for d in derivatives])

    return tables
Exemplo n.º 44
0
def _extract_element_data(element_map, classnames):
    "Extract element data for psi_tables"

    # Iterate over map
    element_data = {}
    for elements in element_map.values():
        for ufl_element, counter in elements.items():

            # Create corresponding FIAT element
            fiat_element = create_element(ufl_element)

            # Compute value size
            value_size = product(ufl_element.value_shape())

            # Get element classname
            element_classname = classnames["finite_element"][ufl_element]

            # Store data
            element_data[counter] = {"physical_value_size": value_size,
                                     "num_element_dofs": fiat_element.space_dimension(),
                                     "classname": element_classname}

    return element_data
Exemplo n.º 45
0
def _tabulate_coordinate_mapping_basis(ufl_element):
    # TODO: Move this function to a table generation module?

    # Get scalar element, assuming coordinates are represented
    # with a VectorElement of scalar subelements
    selement = ufl_element.sub_elements()[0]

    fiat_element = create_element(selement)
    cell = selement.cell()
    tdim = cell.topological_dimension()

    tables = {}

    # Get points
    origo = (0.0,) * tdim
    midpoint = cell_midpoint(cell)

    # Tabulate basis
    t0 = fiat_element.tabulate(1, [origo])
    tm = fiat_element.tabulate(1, [midpoint])

    # Get basis values at cell origo
    tables["x0"] = t0[(0,) * tdim][:, 0]

    # Get basis values at cell midpoint
    tables["xm"] = tm[(0,) * tdim][:, 0]

    # Single direction derivatives, e.g. [(1,0), (0,1)] in 2d
    derivatives = [(0,) * i + (1,) + (0,) * (tdim - 1 - i) for i in range(tdim)]

    # Get basis derivative values at cell origo
    tables["J0"] = numpy.asarray([t0[d][:, 0] for d in derivatives])

    # Get basis derivative values at cell midpoint
    tables["Jm"] = numpy.asarray([tm[d][:, 0] for d in derivatives])

    return tables
Exemplo n.º 46
0
def get_data(ufl_element):
    "Get needed data to run tests."

    # Create fiat element.
    element = create_element(ufl_element)

    # The derivative order that we are interested in is the degree of the element.
    if isinstance(element, FFCMixedElement):
        deriv_order = max([e.degree() for e in element.elements()])
    else:
        deriv_order = element.degree()

    # Get coordinates of the reference cell.
    cell = ufl_element.cell()
    ref_coords = reference_cell(cell.cellname()).get_vertices()

    # Get the locations of the fiat element dofs.
    elem_points =  [list(L.pt_dict.keys())[0] for L in element.dual_basis()]

    # Add some random points.
    geo_dim = cell.geometric_dimension()
    points = elem_points + random_points[geo_dim]

    return (element, points, geo_dim, ref_coords, deriv_order)
Exemplo n.º 47
0
def get_data(ufl_element):
    "Get needed data to run tests."

    # Create fiat element.
    element = create_element(ufl_element)

    # The derivative order that we are interested in is the degree of the element.
    if isinstance(element, FFCMixedElement):
        deriv_order = max([e.degree() for e in element.elements()])
    else:
        deriv_order = element.degree()

    # Get coordinates of the reference cell.
    cell = ufl_element.cell()
    ref_coords = reference_cell(cell.cellname()).get_vertices()

    # Get the locations of the fiat element dofs.
    elem_points = [list(L.pt_dict.keys())[0] for L in element.dual_basis()]

    # Add some random points.
    geo_dim = cell.geometric_dimension()
    points = elem_points + random_points[geo_dim]

    return (element, points, geo_dim, ref_coords, deriv_order)
Exemplo n.º 48
0
def test_continuous_lagrange_quadrilateral(degree, expected_dim):
    "Test space dimensions of continuous TensorProduct elements (quadrilateral)."
    P = create_element(FiniteElement("Lagrange", "quadrilateral", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 49
0
def test_discontinuous_lagrange(degree, expected_dim):
    "Test space dimensions of discontinuous Lagrange elements."
    P = create_element(FiniteElement("DG", "triangle", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 50
0
def test_hhj(degree, expected_dim):
    "Test space dimensions of Hellan-Herrmann-Johnson element."
    P = create_element(FiniteElement("HHJ", "triangle", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 51
0
    def __init__(self, monomial):
        "Create transformed monomial from given monomial."

        # Reset monomial data
        self.float_value = monomial.float_value
        self.determinants = []
        self.coefficients = []
        self.transforms = []
        self.arguments = []

        # Reset index counters
        _reset_indices()

        # Initialize index map
        index_map = {}

        # Iterate over factors
        for f in monomial.factors:

            # Create FIAT element
            ufl_element = f.element()
            fiat_element = create_element(ufl_element)

            # Note nifty aspect here: when gdim != tdim, it might be
            # (in particular, is for H(div)/H(curl), that the value
            # dimension is different for the physical and reference
            # elements.

            # Get number of components
            # FIXME: Can't handle tensor-valued elements: vdim = shape[0]
            shape = ufl_element.value_shape()
            assert(len(shape) <= 1), \
                "MonomialTransformation does not handle tensor-valued elements"
            if len(shape) == 0:
                vdim = 1
            else:
                vdim = shape[0]

            # Extract dimensions
            sdim = fiat_element.space_dimension()
            cell = ufl_element.cell()
            gdim = cell.geometric_dimension()
            tdim = cell.topological_dimension()

            # Extract basis function index and coefficients
            if isinstance(f.function, Argument):
                vindex = MonomialIndex(index_type=MonomialIndex.PRIMARY,
                                       index_range=list(range(sdim)),
                                       index_id=f.index())

            elif isinstance(f.function, Coefficient):
                vindex = MonomialIndex(index_range=list(range(sdim)))
                coefficient = MonomialCoefficient(vindex, f.index())
                self.coefficients.append(coefficient)

            # Extract components
            components = self._extract_components(f, index_map, vdim)

            if len(components) > 1:
                raise MonomialException("Can only handle rank 0 or rank 1 tensors.")

            # Handle non-affine mappings (Piola)
            if len(components) > 0:

                # We can only handle rank 1 elements for now
                component = components[0]

                # Get mapping (all need to be equal)
                mappings = []
                for i in component.index_range:
                    (offset, ufl_sub_element) = ufl_element.extract_component(i)
                    fiat_sub_element = create_element(ufl_sub_element)
                    mappings.extend(fiat_sub_element.mapping())
                if not all_equal(mappings):
                    raise MonomialException("Mappings differ: " + str(mappings))
                mapping = mappings[0]

                # Get component index relative to its sub element and its sub element
                (component_index, sub_element) = ufl_element.extract_component(component.index_range[0])

                # Get offset
                if len(component_index) == 0:
                    offset = 0
                else:
                    offset = component.index_range[0] - component_index[0]

                # MER: Need to handle mappings in special ways if gdim
                # != tdim and some Piolas are present. This could
                # probably be merged with the offset code above, but I
                # was not able to wrap my head around the offsets
                # always referring to component.index_range[0].
                if (gdim != tdim):
                    assert len(component.index_range) == 1, \
                        "Component transform not implemented for this case. Please request this feature."
                    component, offset = transform_component(component.index_range[0], offset, ufl_element)
                    component = MonomialIndex(index_type=MonomialIndex.FIXED,
                                              index_range=[component], index_id=None)
                    components = [component, ]

                # Add transforms where appropriate
                if mapping == "contravariant piola":
                    # phi(x) = (det J)^{-1} J Phi(X)
                    index0 = component
                    index1 = MonomialIndex(index_range=list(range(tdim))) + offset
                    transform = MonomialTransform(index0, index1,
                                                  MonomialTransform.J,
                                                  f.restriction, offset)
                    self.transforms.append(transform)
                    determinant = MonomialDeterminant(power=-1,
                                                      restriction=f.restriction)
                    self.determinants.append(determinant)
                    components[0] = index1
                elif mapping == "covariant piola":
                    # phi(x) = J^{-T} Phi(X)
                    index0 = MonomialIndex(index_range=list(range(tdim))) + offset
                    index1 = component
                    transform = MonomialTransform(index0, index1,
                                                  MonomialTransform.JINV,
                                                  f.restriction, offset)
                    self.transforms.append(transform)
                    components[0] = index0

            # Extract derivatives / transforms
            derivatives = []
            for d in f.derivatives:
                index0 = MonomialIndex(index_range=list(range(tdim)))
                if d in index_map:
                    index1 = index_map[d]
                elif isinstance(d, FixedIndex):
                    index1 = MonomialIndex(index_type=MonomialIndex.FIXED,
                                           index_range=[int(d)],
                                           index_id=int(d))
                else:
                    index1 = MonomialIndex(index_range=list(range(gdim)))
                index_map[d] = index1
                transform = MonomialTransform(index0, index1, MonomialTransform.JINV, f.restriction, 0)

                self.transforms.append(transform)
                derivatives.append(index0)

            # Extract restriction
            restriction = f.restriction

            # Create basis function
            v = MonomialArgument(ufl_element, vindex, components, derivatives, restriction)
            self.arguments.append(v)

        # Figure out secondary and auxiliary indices
        internal_indices = self._extract_internal_indices(None)
        external_indices = self._extract_external_indices(None)
        for i in internal_indices + external_indices:

            # Skip already visited indices
            if not i.index_type is None:
                continue

            # Set index type and id
            num_internal = len([j for j in internal_indices if j == i])
            num_external = len([j for j in external_indices if j == i])

            if num_internal == 1 and num_external == 1:
                i.index_type = MonomialIndex.SECONDARY
                i.index_id   = _next_secondary_index()
            elif num_internal == 2 and num_external == 0:
                i.index_type = MonomialIndex.INTERNAL
                i.index_id   = _next_internal_index()
            elif num_internal == 0 and num_external == 2:
                i.index_type = MonomialIndex.EXTERNAL
                i.index_id   = _next_external_index()
            else:
                raise Exception("Summation index does not appear exactly twice: %s" % str(i))
Exemplo n.º 52
0
def test_regge(degree, expected_dim):
    "Test space dimensions of generalized Regge element."
    P = create_element(FiniteElement("Regge", "triangle", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 53
0
def test_discontinuous_lagrange(degree, expected_dim):
    "Test space dimensions of discontinuous Lagrange elements."
    P = create_element(FiniteElement("DG", "triangle", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 54
0
def test_continuous_lagrange_quadrilateral(degree, expected_dim):
    "Test space dimensions of continuous TensorProduct elements (quadrilateral)."
    P = create_element(FiniteElement("Lagrange", "quadrilateral", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 55
0
def test_regge(degree, expected_dim):
    "Test space dimensions of generalized Regge element."
    P = create_element(FiniteElement("Regge", "triangle", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 56
0
Arquivo: plot.py Projeto: doru1004/FFC
def create_dof_models(element):
    "Create Soya3D models for dofs."

    # Flags for whether to flip and center arrows
    directional = {"PointScaledNormalEval": (True,  False),
                   "PointEdgeTangent":      (False, True),
                   "PointFaceTangent":      (False, True)}

    # Elements not supported fully by FIAT
    unsupported = {"Argyris":            argyris_dofs,
                   "Arnold-Winther":     arnold_winther_dofs,
                   "Hermite":            hermite_dofs,
                   "Mardal-Tai-Winther": mardal_tai_winther_dofs,
                   "Morley":             morley_dofs}

    # Check if element is supported
    family = element.family()
    if not family in unsupported:
        # Create FIAT element and get dofs
        fiat_element = create_element(element)
        dofs = [(dof.get_type_tag(), dof.get_point_dict()) for dof in fiat_element.dual_basis()]

    else:

        # Bybass FIAT and set the dofs ourselves
        dofs = unsupported[family](element)

    # Iterate over dofs and add models
    models = []
    num_moments = 0
    for (dof_type, L) in dofs:

        # Check type of dof
        if dof_type == "PointEval":

            # Point evaluation, just get point
            points = list(L.keys())
            if not len(points) == 1:
                error("Strange dof, single point expected.")
            x = points[0]

            # Generate model
            models.append(PointEvaluation(x))

        elif dof_type == "PointDeriv":

            # Evaluation of derivatives at point
            points = list(L.keys())
            if not len(points) == 1:
                error("Strange dof, single point expected.")
            x = points[0]

            # Generate model
            models.append(PointDerivative(x))

        elif dof_type == "PointSecondDeriv":

            # Evaluation of derivatives at point
            points = list(L.keys())
            if not len(points) == 1:
                error("Strange dof, single point expected.")
            x = points[0]

            # Generate model
            models.append(PointSecondDerivative(x))

        elif dof_type in directional:

            # Normal evaluation, get point and normal
            points = list(L.keys())
            if not len(points) == 1:
                error("Strange dof, single point expected.")
            x = points[0]
            n = [xx[0] for xx in L[x]]

            # Generate model
            flip, center = directional[dof_type]
            models.append(DirectionalEvaluation(x, n, flip, center))

        elif dof_type == "PointNormalDeriv":

            # Evaluation of derivatives at point
            points = list(L.keys())
            if not len(points) == 1:
                error("Strange dof, single point expected.")
            x = points[0]
            n = [xx[0] for xx in L[x]]

            # Generate model
            models.append(DirectionalDerivative(x, n))

        elif dof_type in ("FrobeniusIntegralMoment", "IntegralMoment", "ComponentPointEval"):

            # Generate model
            models.append(IntegralMoment(element.cell().cellname(), num_moments))

            # Count the number of integral moments
            num_moments += 1

        else:
            error("Unable to plot dof, unhandled dof type: %s" % str(dof_type))

    return models, num_moments
Exemplo n.º 57
0
def test_hhj(degree, expected_dim):
    "Test space dimensions of Hellan-Herrmann-Johnson element."
    P = create_element(FiniteElement("HHJ", "triangle", degree))
    assert P.space_dimension() == expected_dim
Exemplo n.º 58
0
def tabulate_basis(sorted_integrals, form_data, itg_data):
    "Tabulate the basisfunctions and derivatives."

    # MER: Note to newbies: this code assumes that each integral in
    # the dictionary of sorted_integrals that enters here, has a
    # unique number of quadrature points ...

    # Initialise return values.
    quadrature_rules = {}
    psi_tables = {}
    integrals = {}
    avg_elements = {"cell": [], "facet": []}

    # Get some useful variables in short form
    integral_type = itg_data.integral_type
    cell = itg_data.domain.ufl_cell()
    cellname = cell.cellname()
    tdim = itg_data.domain.topological_dimension()
    entity_dim = integral_type_to_entity_dim(integral_type, tdim)
    num_entities = num_cell_entities[cellname][entity_dim]

    # Create canonical ordering of quadrature rules
    rules = sorted(sorted_integrals.keys())

    # Loop the quadrature points and tabulate the basis values.
    for rule in rules:
        scheme, degree = rule

        # --------- Creating quadrature rule
        # Make quadrature rule and get points and weights.
        (points, weights) = create_quadrature_points_and_weights(integral_type,
                                                                 cell, degree,
                                                                 scheme)

        # The TOTAL number of weights/points
        num_points = None if weights is None else len(weights)

        # Add points and rules to dictionary
        if num_points in quadrature_rules:
            error("This number of points is already present in the weight table: " + repr(quadrature_rules))
        quadrature_rules[num_points] = (weights, points)

        # --------- Store integral
        # Add the integral with the number of points as a key to the
        # return integrals.
        integral = sorted_integrals[rule]
        if num_points in integrals:
            error("This number of points is already present in the integrals: " + repr(integrals))
        integrals[num_points] = integral

        # --------- Analyse UFL elements in integral

        # Get all unique elements in integral.
        ufl_elements = [form_data.element_replace_map[e]
                        for e in extract_unique_elements(integral)]

        # Insert elements for x and J
        domain = integral.ufl_domain()  # FIXME: For all domains to be sure? Better to rewrite though.
        x_element = domain.ufl_coordinate_element()
        if x_element not in ufl_elements:
            if integral_type in custom_integral_types:
                # FIXME: Not yet implemented, in progress
                # warning("Vector elements not yet supported in custom integrals so element for coordinate function x will not be generated.")
                pass
            else:
                ufl_elements.append(x_element)

        # Find all CellAvg and FacetAvg in integrals and extract
        # elements
        for avg, AvgType in (("cell", CellAvg), ("facet", FacetAvg)):
            expressions = extract_type(integral, AvgType)
            avg_elements[avg] = [form_data.element_replace_map[e]
                                 for expr in expressions
                                 for e in extract_unique_elements(expr)]

        # Find the highest number of derivatives needed for each element
        num_derivatives = _find_element_derivatives(integral.integrand(),
                                                    ufl_elements,
                                                    form_data.element_replace_map)
        # Need at least 1 for the Jacobian
        num_derivatives[x_element] = max(num_derivatives.get(x_element, 0), 1)

        # --------- Evaluate FIAT elements in quadrature points and
        # --------- store in tables

        # Add the number of points to the psi tables dictionary
        if num_points in psi_tables:
            error("This number of points is already present in the psi table: " + repr(psi_tables))
        psi_tables[num_points] = {}

        # Loop FIAT elements and tabulate basis as usual.
        for ufl_element in ufl_elements:
            fiat_element = create_element(ufl_element)

            # Tabulate table of basis functions and derivatives in
            # points
            psi_table = _tabulate_psi_table(integral_type, cellname, tdim,
                                            fiat_element,
                                            num_derivatives[ufl_element],
                                            points)

            # Insert table into dictionary based on UFL elements
            # (None=not averaged)
            avg = None
            psi_tables[num_points][ufl_element] = { avg: psi_table }

    # Loop over elements found in CellAvg and tabulate basis averages
    num_points = 1
    for avg in ("cell", "facet"):
        # Doesn't matter if it's exterior or interior
        if avg == "cell":
            avg_integral_type = "cell"
        elif avg == "facet":
            avg_integral_type = "exterior_facet"

        for element in avg_elements[avg]:
            fiat_element = create_element(element)

            # Make quadrature rule and get points and weights.
            (points, weights) = create_quadrature_points_and_weights(avg_integral_type, cell, element.degree(), "default")
            wsum = sum(weights)

            # Tabulate table of basis functions and derivatives in
            # points
            entity_psi_tables = _tabulate_psi_table(avg_integral_type,
                                                    cellname, tdim,
                                                    fiat_element, 0, points)
            rank = len(element.value_shape())

            # Hack, duplicating table with per-cell values for each
            # facet in the case of cell_avg(f) in a facet integral
            if num_entities > len(entity_psi_tables):
                assert len(entity_psi_tables) == 1
                assert avg_integral_type == "cell"
                assert "facet" in integral_type
                v, = sorted(entity_psi_tables.values())
                entity_psi_tables = dict((e, v) for e in range(num_entities))

            for entity, deriv_table in sorted(entity_psi_tables.items()):
                deriv, = sorted(deriv_table.keys())  # Not expecting derivatives of averages
                psi_table = deriv_table[deriv]

                if rank:
                    # Compute numeric integral
                    num_dofs, num_components, num_points = psi_table.shape
                    if num_points != len(weights):
                        error("Weights and table shape does not match.")
                    avg_psi_table = numpy.asarray([[[numpy.dot(psi_table[j, k, :], weights) / wsum]
                                                    for k in range(num_components)]
                                                   for j in range(num_dofs)])
                else:
                    # Compute numeric integral
                    num_dofs, num_points = psi_table.shape
                    if num_points != len(weights):
                        error("Weights and table shape does not match.")
                    avg_psi_table = numpy.asarray([[numpy.dot(psi_table[j, :],
                                                              weights) / wsum] for j in range(num_dofs)])

                # Insert table into dictionary based on UFL elements
                insert_nested_dict(psi_tables, (num_points, element, avg,
                                                entity, deriv), avg_psi_table)

    return (integrals, psi_tables, quadrature_rules)