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
Beispiel #2
0
def compute_integral_ir(itg_data,
                        form_data,
                        form_id,
                        element_numbers,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing tensor representation")

    # Extract monomial representation
    integrands = [itg.integrand() for itg in itg_data.integrals]
    monomial_form = extract_monomial_form(integrands, form_data.function_replace_map)

    # Transform monomial form to reference element
    transform_monomial_form(monomial_form)

    # Get some integral properties
    integral_type = itg_data.integral_type
    quadrature_degree = itg_data.metadata["quadrature_degree"]
    quadrature_rule = itg_data.metadata["quadrature_rule"]

    # Get some cell properties
    cell = itg_data.domain.ufl_cell()
    num_facets = cell.num_facets()

    # Helper to simplify code below
    compute_terms = lambda i, j: _compute_terms(monomial_form,
                                           i, j,
                                           integral_type,
                                           quadrature_degree,
                                           quadrature_rule,
                                           cell)

    # Compute representation of cell tensor
    if integral_type == "cell":
        # Compute sum of tensor representations
        terms = compute_terms(None, None)

    elif integral_type == "exterior_facet":
        # Compute sum of tensor representations for each facet
        terms = [compute_terms(i, None) for i in range(num_facets)]

    elif integral_type == "interior_facet":
        # Compute sum of tensor representations for each facet-facet pair
        terms = [[compute_terms(i, j) for j in range(num_facets)] for i in range(num_facets)]
        for i in range(num_facets):
            for j in range(num_facets):
                reorder_entries(terms[i][j])

    else:
        error("Unhandled domain type: " + str(integral_type))

    # Initialize representation and store terms
    ir = initialize_integral_ir("tensor", itg_data, form_data, form_id)
    ir["AK"] = terms

    return ir
Beispiel #3
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
Beispiel #4
0
def compute_integral_ir(itg_data, form_data, form_id, element_numbers,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing tensor representation")

    # Extract monomial representation
    integrands = [itg.integrand() for itg in itg_data.integrals]
    monomial_form = extract_monomial_form(integrands,
                                          form_data.function_replace_map)

    # Transform monomial form to reference element
    transform_monomial_form(monomial_form)

    # Get some integral properties
    integral_type = itg_data.integral_type
    quadrature_degree = itg_data.metadata["quadrature_degree"]
    quadrature_rule = itg_data.metadata["quadrature_rule"]

    # Get some cell properties
    cell = itg_data.domain.cell()
    cellname = cell.cellname()
    facet_cellname = cell.facet_cellname()
    num_facets = cell.num_facets()

    # Helper to simplify code below
    compute_terms = lambda i, j: _compute_terms(
        monomial_form, i, j, integral_type, quadrature_degree, quadrature_rule,
        cellname, facet_cellname)

    # Compute representation of cell tensor
    if integral_type == "cell":
        # Compute sum of tensor representations
        terms = compute_terms(None, None)

    elif integral_type == "exterior_facet":
        # Compute sum of tensor representations for each facet
        terms = [compute_terms(i, None) for i in range(num_facets)]

    elif integral_type == "interior_facet":
        # Compute sum of tensor representations for each facet-facet pair
        terms = [[compute_terms(i, j) for j in range(num_facets)]
                 for i in range(num_facets)]
        for i in range(num_facets):
            for j in range(num_facets):
                reorder_entries(terms[i][j])

    else:
        error("Unhandled domain type: " + str(integral_type))

    # Initialize representation and store terms
    ir = initialize_integral_ir("tensor", itg_data, form_data, form_id)
    ir["AK"] = terms

    return ir
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
Beispiel #6
0
def compute_integral_ir(integral_data, form_data, form_id, element_numbers,
                        classnames, parameters):
    "Compute intermediate represention of integral."

    info("Computing tsfc representation")

    # Initialise representation
    ir = initialize_integral_ir("tsfc", integral_data, form_data, form_id)

    # TSFC treats None and unset differently, so remove None values.
    parameters = {k: v for k, v in parameters.items() if v is not None}

    # Delay TSFC compilation
    ir["compile_integral"] = (integral_data, form_data, None, parameters)

    return ir
Beispiel #7
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
Beispiel #8
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
Beispiel #9
0
def compute_integral_ir(integral_data,
                        form_data,
                        form_id,
                        element_numbers,
                        classnames,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing tsfc representation")

    # Initialise representation
    ir = initialize_integral_ir("tsfc", integral_data, form_data, form_id)

    # TSFC treats None and unset differently, so remove None values.
    parameters = {k: v for k, v in parameters.items() if v is not None}

    # Delay TSFC compilation
    ir["compile_integral"] = (integral_data, form_data, None, parameters)

    return ir
def compute_integral_ir(itg_data, form_data, form_id, element_numbers,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing quadrature representation")

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

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

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

    # Tabulate quadrature points and basis function values in these points
    integrals_dict, psi_tables, quadrature_rules = \
        tabulate_basis(sorted_integrals, form_data, itg_data)

    # Save tables for quadrature weights and points
    ir["quadrature_weights"] = quadrature_rules  # TODO: Rename this ir entry to 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
    ]

    # Select transformer
    if ir["optimise_parameters"]["optimisation"] or parameters["pyop2-ir"]:
        QuadratureTransformerClass = QuadratureTransformerOpt
    else:
        QuadratureTransformerClass = QuadratureTransformer

    # Create transformer
    transformer = QuadratureTransformerClass(
        psi_tables, quadrature_rules, itg_data.domain.geometric_dimension(),
        itg_data.domain.topological_dimension(), ir["entitytype"],
        form_data.function_replace_map, ir["optimise_parameters"], parameters)

    # Transform integrals.
    cell = itg_data.domain.ufl_cell()
    ir["trans_integrals"] = _transform_integrals_by_type(
        ir, transformer, integrals_dict, itg_data.integral_type)

    # 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"] = {}

    # Add local tensor entry dimensions
    ir["tensor_entry_size"] = tuple([1] * form_data.rank)

    # Add number of coefficients
    ir["num_coefficients"] = form_data.num_coefficients

    # Extract element data for psi_tables, needed for runtime quadrature.
    # This is used by integral type custom_integral.
    ir["element_data"] = _extract_element_data(transformer.element_map,
                                               element_numbers)

    return ir
Beispiel #11
0
def compute_integral_ir(itg_data,
                        form_data,
                        form_id,
                        element_numbers,
                        classnames,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing uflacs representation")

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

    # Store element classnames
    ir["classnames"] = classnames

    # Get element space dimensions
    unique_elements = element_numbers.keys()
    ir["element_dimensions"] = { ufl_element: create_element(ufl_element).space_dimension()
                                 for ufl_element in unique_elements }

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

    # Compute shape of element tensor
    if ir["integral_type"] == "interior_facet":
        ir["tensor_shape"] = [2 * dim for dim in argument_dimensions]
    else:
        ir["tensor_shape"] = argument_dimensions

    integral_type = itg_data.integral_type
    cell = itg_data.domain.ufl_cell()

    if integral_type in custom_integral_types:
        # Set quadrature degree to twice the highest element degree, to get
        # enough points to identify basis functions via table computations
        max_element_degree = max([1] + [ufl_element.degree() for ufl_element in unique_elements])
        rules = [("default", 2*max_element_degree)]
        quadrature_integral_type = "cell"
    else:
        # Collect which quadrature rules occur in integrals
        default_scheme = itg_data.metadata["quadrature_degree"]
        default_degree = itg_data.metadata["quadrature_rule"]
        rules = collect_quadrature_rules(
            itg_data.integrals, default_scheme, default_degree)
        quadrature_integral_type = integral_type

    # Compute actual points and weights
    quadrature_rules, quadrature_rule_sizes = compute_quadrature_rules(
        rules, quadrature_integral_type, cell)

    # Store quadrature rules in format { num_points: (points, weights) }
    ir["quadrature_rules"] = quadrature_rules

    # Store the fake num_points for analysis in custom integrals
    if integral_type in custom_integral_types:
        ir["fake_num_points"], = quadrature_rules.keys()

    # Group and accumulate integrals on the format { num_points: integral data }
    sorted_integrals = accumulate_integrals(itg_data, quadrature_rule_sizes)

    # Build coefficient numbering for UFC interface here, to avoid
    # renumbering in UFL and application of replace mapping
    if True:
        # Using the mapped coefficients, numbered by UFL
        coefficient_numbering = {}
        sorted_coefficients = sorted_by_count(form_data.function_replace_map.keys())
        for i, f in enumerate(sorted_coefficients):
            g = form_data.function_replace_map[f]
            coefficient_numbering[g] = i
            assert i == g.count()

        # Replace coefficients so they all have proper element and domain for what's to come
        # TODO: We can avoid the replace call when proper Expression support is in place
        #       and element/domain assignment is removed from compute_form_data.
        integrands = {
            num_points: replace(sorted_integrals[num_points].integrand(), form_data.function_replace_map)
            for num_points in sorted(sorted_integrals)
            }
    else:
        pass
        #coefficient_numbering = {}
        #coefficient_element = {}
        #coefficient_domain = {}
        #sorted_coefficients = sorted_by_count(form_data.function_replace_map.keys())
        #for i, f in enumerate(sorted_coefficients):
        #    g = form_data.function_replace_map[f]
        #    coefficient_numbering[f] = i
        #    coefficient_element[f] = g.ufl_element()
        #    coefficient_domain[f] = g.ufl_domain()
        #integrands = {
        #    num_points: sorted_integrals[num_points].integrand()
        #    for num_points in sorted(sorted_integrals)
        #    }
        # then pass coefficient_element and coefficient_domain to the uflacs ir as well


    # Build the more uflacs-specific intermediate representation
    uflacs_ir = build_uflacs_ir(itg_data.domain.ufl_cell(),
                                itg_data.integral_type,
                                ir["entitytype"],
                                integrands,
                                ir["tensor_shape"],
                                coefficient_numbering,
                                quadrature_rules,
                                parameters)
    ir.update(uflacs_ir)

    return ir
Beispiel #12
0
def compute_integral_ir(itg_data,
                        form_data,
                        form_id,
                        element_numbers,
                        classnames,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing quadrature representation")

    issue_deprecation_warning()

    set_float_formatting(parameters["precision"])

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

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

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

    # Tabulate quadrature points and basis function values in these
    # points
    integrals_dict, psi_tables, quadrature_rules = \
        tabulate_basis(sorted_integrals, form_data, itg_data)

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

    # Select transformer
    if ir["optimise_parameters"]["optimisation"]:
        QuadratureTransformerClass = QuadratureTransformerOpt
    else:
        QuadratureTransformerClass = QuadratureTransformer

    # Create transformer
    transformer = QuadratureTransformerClass(psi_tables,
                                             quadrature_rules,
                                             itg_data.domain.geometric_dimension(),
                                             itg_data.domain.topological_dimension(),
                                             ir["entitytype"],
                                             form_data.function_replace_map,
                                             ir["optimise_parameters"])

    # Transform integrals.
    cell = itg_data.domain.ufl_cell()
    ir["trans_integrals"] = _transform_integrals_by_type(ir, transformer,
                                                         integrals_dict,
                                                         itg_data.integral_type,
                                                         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"] = {}

    # Extract element data for psi_tables, needed for runtime
    # quadrature.  This is used by integral type custom_integral.
    ir["element_data"] = _extract_element_data(transformer.element_map, classnames)

    return ir
def compute_integral_ir(itg_data,
                        form_data,
                        form_id,
                        parameters):
    "Compute intermediate represention of integral."

    info("Computing tensor representation")

    # Extract monomial representation
    monomial_form = extract_monomial_form(itg_data.integrals, form_data.function_replace_map)

    # Transform monomial form to reference element
    transform_monomial_form(monomial_form)

    # Get some cell properties
    cell = form_data.cell
    cellname = cell.cellname()
    facet_cellname = cell.facet_cellname()
    num_facets = cellname_to_num_entities[cellname][-2]

    # Initialize representation
    ir = initialize_integral_ir("tensor", itg_data, form_data, form_id)
    ir["rank"] = form_data.rank

    # Compute representation of cell tensor
    quadrature_degree = itg_data.metadata["quadrature_degree"]
    quadrature_rule = itg_data.metadata["quadrature_rule"]
    if itg_data.domain_type == "cell":

        # Compute sum of tensor representations
        ir["AK"] = _compute_terms(monomial_form,
                                  None, None,
                                  itg_data.domain_type,
                                  quadrature_degree,
                                  quadrature_rule,
                                  cellname,
                                  facet_cellname)

    elif itg_data.domain_type == "exterior_facet":

        # Compute sum of tensor representations for each facet
        terms = [None for i in range(num_facets)]
        for i in range(num_facets):
            terms[i] = _compute_terms(monomial_form,
                                      i, None,
                                      itg_data.domain_type,
                                      quadrature_degree,
                                      quadrature_rule,
                                      cellname,
                                      facet_cellname)
        ir["AK"] = terms

    elif itg_data.domain_type == "interior_facet":

        # Compute sum of tensor representations for each facet-facet pair
        terms = [[None for j in range(num_facets)] for i in range(num_facets)]
        for i in range(num_facets):
            for j in range(num_facets):
                terms[i][j] = _compute_terms(monomial_form,
                                             i, j,
                                             itg_data.domain_type,
                                             quadrature_degree,
                                             quadrature_rule,
                                             cellname,
                                             facet_cellname)
                reorder_entries(terms[i][j])
        ir["AK"] = terms

    else:
        error("Unhandled domain type: " + str(itg_data.domain_type))

    return ir