Ejemplo n.º 1
0
 def coordinate_derivative(self, o):
     from ufl.algorithms import extract_unique_elements
     spaces = set(c.family() for c in extract_unique_elements(o))
     unsupported_spaces = {"Argyris", "Bell", "Hermite", "Morley"}
     if spaces & unsupported_spaces:
         error("CoordinateDerivative is not supported for elements of type %s. "
               "This is because their pullback is not implemented in UFL." % unsupported_spaces)
     f, w, v, cd = o.ufl_operands
     f = self(f)  # transform f
     rules = CoordinateDerivativeRuleset(w, v, cd)
     return map_expr_dag(rules, f)
Ejemplo n.º 2
0
 def coordinate_derivative(self, o, f, w, v, cd):
     from ufl.algorithms import extract_unique_elements
     spaces = set(c.family() for c in extract_unique_elements(o))
     unsupported_spaces = {"Argyris", "Bell", "Hermite", "Morley"}
     if spaces & unsupported_spaces:
         error("CoordinateDerivative is not supported for elements of type %s. "
               "This is because their pullback is not implemented in UFL." % unsupported_spaces)
     _, w, v, cd = o.ufl_operands
     rules = CoordinateDerivativeRuleset(w, v, cd)
     key = (CoordinateDerivativeRuleset, w, v, cd)
     return map_expr_dag(rules, f, vcache=self.vcache[key], rcache=self.rcache[key])
Ejemplo n.º 3
0
def test_extract_elements_and_extract_unique_elements(forms):
    b = forms[2]
    integrals = b.integrals_by_type("cell")
    integrand = integrals[0].integrand()

    element1 = FiniteElement("CG", triangle, 1)
    element2 = FiniteElement("CG", triangle, 1)

    v = TestFunction(element1)
    u = TrialFunction(element2)

    a = u * v * dx
    assert extract_elements(a) == (element1, element2)
    assert extract_unique_elements(a) == (element1,)
Ejemplo n.º 4
0
def test_extract_elements_and_extract_unique_elements(forms):
    b = forms[2]
    integrals = b.integrals_by_type("cell")
    integrand = integrals[0].integrand()

    element1 = FiniteElement("CG", triangle, 1)
    element2 = FiniteElement("CG", triangle, 1)

    v = TestFunction(element1)
    u = TrialFunction(element2)

    a = u * v * dx
    assert extract_elements(a) == (element1, element2)
    assert extract_unique_elements(a) == (element1, )
Ejemplo n.º 5
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)
Ejemplo n.º 6
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)
def _tabulate_basis(sorted_integrals, domain_type, form_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_weights = {}
    psi_tables = {}
    integrals = {}
    avg_elements = { "cell": [], "facet": [] }

    # Loop the quadrature points and tabulate the basis values.
    for pr, integral in sorted_integrals.iteritems():

        # Extract number of points and the rule.
        degree, rule = pr

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

        # 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)]

        # Create a list of equivalent FIAT elements (with same
        # ordering of elements).
        fiat_elements = [create_element(e) for e in ufl_elements]

        # Make quadrature rule and get points and weights.
        (points, weights) = _create_quadrature_points_and_weights(domain_type, form_data.cell, degree, rule)

        # The TOTAL number of weights/points
        len_weights = len(weights)

        # Assert that this is unique
        ffc_assert(len_weights not in quadrature_weights, \
                    "This number of points is already present in the weight table: " + repr(quadrature_weights))
        ffc_assert(len_weights not in psi_tables, \
                    "This number of points is already present in the psi table: " + repr(psi_tables))
        ffc_assert(len_weights not in integrals, \
                    "This number of points is already present in the integrals: " + repr(integrals))

        # Add points and rules to dictionary.
        quadrature_weights[len_weights] = (weights, points)

        # Add the number of points to the psi tables dictionary.
        psi_tables[len_weights] = {}

        # Add the integral with the number of points as a key to the return integrals.
        integrals[len_weights] = integral

        # Find the highest number of derivatives needed for each element
        num_derivatives = _find_element_derivatives(integral.integrand(), ufl_elements,
                                                    form_data.element_replace_map)

        # Loop FIAT elements and tabulate basis as usual.
        for i, element in enumerate(fiat_elements):
            # Tabulate table of basis functions and derivatives in points
            psi_table = _tabulate_psi_table(domain_type, form_data.cell, element,
                                        num_derivatives[ufl_elements[i]], points)

            # Insert table into dictionary based on UFL elements. (None=not averaged)
            psi_tables[len_weights][ufl_elements[i]] = { None: psi_table }

    # Loop over elements found in CellAvg and tabulate basis averages
    len_weights = 1
    for avg in ("cell", "facet"):
        # Doesn't matter if it's exterior or interior
        if avg == "cell":
            avg_domain_type = "cell"
        elif avg == "facet":
            avg_domain_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_domain_type, form_data.cell, element.degree(), "default")
            wsum = sum(weights)

            # Tabulate table of basis functions and derivatives in points
            entity_psi_tables = _tabulate_psi_table(avg_domain_type, form_data.cell, 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
            actual_entities = _tabulate_entities(domain_type, form_data.cell)
            if len(actual_entities) > len(entity_psi_tables):
                assert len(entity_psi_tables) == 1
                assert avg_domain_type == "cell"
                assert "facet" in domain_type
                v, = entity_psi_tables.values()
                entity_psi_tables = dict((e, v) for e in actual_entities)

            for entity, deriv_table in entity_psi_tables.items():
                deriv, = list(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
                    ffc_assert(num_points == len(weights), "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
                    ffc_assert(num_points == len(weights), "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, (len_weights, element, avg, entity, deriv), avg_psi_table)

    return (integrals, psi_tables, quadrature_weights)
Ejemplo n.º 8
0
def _tabulate_basis(sorted_integrals, domain_type, form_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_weights = {}
    psi_tables = {}
    integrals = {}
    avg_elements = {"cell": [], "facet": []}

    # Loop the quadrature points and tabulate the basis values.
    for pr, integral in sorted_integrals.iteritems():

        # Extract number of points and the rule.
        degree, rule = pr

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

        # 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)
            ]

        # Create a list of equivalent FIAT elements (with same
        # ordering of elements).
        fiat_elements = [create_element(e) for e in ufl_elements]

        # Make quadrature rule and get points and weights.
        (points, weights) = _create_quadrature_points_and_weights(
            domain_type, form_data.cell, degree, rule)

        # The TOTAL number of weights/points
        len_weights = len(weights)

        # Assert that this is unique
        ffc_assert(len_weights not in quadrature_weights, \
                    "This number of points is already present in the weight table: " + repr(quadrature_weights))
        ffc_assert(len_weights not in psi_tables, \
                    "This number of points is already present in the psi table: " + repr(psi_tables))
        ffc_assert(len_weights not in integrals, \
                    "This number of points is already present in the integrals: " + repr(integrals))

        # Add points and rules to dictionary.
        quadrature_weights[len_weights] = (weights, points)

        # Add the number of points to the psi tables dictionary.
        psi_tables[len_weights] = {}

        # Add the integral with the number of points as a key to the return integrals.
        integrals[len_weights] = integral

        # Find the highest number of derivatives needed for each element
        num_derivatives = _find_element_derivatives(
            integral.integrand(), ufl_elements, form_data.element_replace_map)

        # Loop FIAT elements and tabulate basis as usual.
        for i, element in enumerate(fiat_elements):
            # Tabulate table of basis functions and derivatives in points
            psi_table = _tabulate_psi_table(domain_type, form_data.cell,
                                            element,
                                            num_derivatives[ufl_elements[i]],
                                            points)

            # Insert table into dictionary based on UFL elements. (None=not averaged)
            psi_tables[len_weights][ufl_elements[i]] = {None: psi_table}

    # Loop over elements found in CellAvg and tabulate basis averages
    len_weights = 1
    for avg in ("cell", "facet"):
        # Doesn't matter if it's exterior or interior
        if avg == "cell":
            avg_domain_type = "cell"
        elif avg == "facet":
            avg_domain_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_domain_type, form_data.cell, element.degree(), "default")
            wsum = sum(weights)

            # Tabulate table of basis functions and derivatives in points
            entity_psi_tables = _tabulate_psi_table(avg_domain_type,
                                                    form_data.cell,
                                                    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
            actual_entities = _tabulate_entities(domain_type, form_data.cell)
            if len(actual_entities) > len(entity_psi_tables):
                assert len(entity_psi_tables) == 1
                assert avg_domain_type == "cell"
                assert "facet" in domain_type
                v, = entity_psi_tables.values()
                entity_psi_tables = dict((e, v) for e in actual_entities)

            for entity, deriv_table in entity_psi_tables.items():
                deriv, = list(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
                    ffc_assert(num_points == len(weights),
                               "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
                    ffc_assert(num_points == len(weights),
                               "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,
                                   (len_weights, element, avg, entity, deriv),
                                   avg_psi_table)

    return (integrals, psi_tables, quadrature_weights)