Beispiel #1
0
    def indexed(self, o, Ap,
                ii):  # TODO: (Partially) duplicated in nesting rules
        # Propagate zeros
        if isinstance(Ap, Zero):
            return self.independent_operator(o)

        # Untangle as_tensor(C[kk], jj)[ii] -> C[ll] to simplify
        # resulting expression
        if isinstance(Ap, ComponentTensor):
            B, jj = Ap.ufl_operands
            if isinstance(B, Indexed):
                C, kk = B.ufl_operands
                kk = list(kk)
                if all(j in kk for j in jj):
                    rep = dict(zip(jj, ii))
                    Cind = [rep.get(k, k) for k in kk]
                    expr = Indexed(C, MultiIndex(tuple(Cind)))
                    assert expr.ufl_free_indices == o.ufl_free_indices
                    assert expr.ufl_shape == o.ufl_shape
                    return expr

        # Otherwise a more generic approach
        r = len(Ap.ufl_shape) - len(ii)
        if r:
            kk = indices(r)
            op = Indexed(Ap, MultiIndex(ii.indices() + kk))
            op = as_tensor(op, kk)
        else:
            op = Indexed(Ap, ii)
        return op
Beispiel #2
0
    def indexed(self, o, Ap,
                ii):  # TODO: (Partially) duplicated in generic rules
        # Reuse if untouched
        if Ap is o.ufl_operands[0]:
            return o

        # Untangle as_tensor(C[kk], jj)[ii] -> C[ll] to simplify
        # resulting expression
        if isinstance(Ap, ComponentTensor):
            B, jj = Ap.ufl_operands
            if isinstance(B, Indexed):
                C, kk = B.ufl_operands

                kk = list(kk)
                if all(j in kk for j in jj):
                    Cind = list(kk)
                    for i, j in zip(ii, jj):
                        Cind[kk.index(j)] = i
                    return Indexed(C, MultiIndex(tuple(Cind)))

        # Otherwise a more generic approach
        r = len(Ap.ufl_shape) - len(ii)
        if r:
            kk = indices(r)
            op = Indexed(Ap, MultiIndex(ii.indices() + kk))
            op = as_tensor(op, kk)
        else:
            op = Indexed(Ap, ii)
        return op
Beispiel #3
0
def _getitem(self, component):

    # Treat component consistently as tuple below
    if not isinstance(component, tuple):
        component = (component, )

    shape = self.ufl_shape

    # Analyse slices (:) and Ellipsis (...)
    all_indices, slice_indices, repeated_indices = create_slice_indices(
        component, shape, self.ufl_free_indices)

    # Check that we have the right number of indices for a tensor with
    # this shape
    if len(shape) != len(all_indices):
        error(
            "Invalid number of indices {0} for expression of rank {1}.".format(
                len(all_indices), len(shape)))

    # Special case for simplifying foo[...] => foo, foo[:] => foo or
    # similar
    if len(slice_indices) == len(all_indices):
        return self

    # Special case for simplifying as_tensor(ai,(i,))[i] => ai
    if isinstance(self, ComponentTensor):
        if all_indices == self.indices().indices():
            return self.ufl_operands[0]

    # Apply all indices to index self, yielding a scalar valued
    # expression
    mi = MultiIndex(all_indices)
    a = Indexed(self, mi)

    # TODO: I think applying as_tensor after index sums results in
    # cleaner expression graphs.

    # If the Ellipsis or any slices were found, wrap as tensor valued
    # with the slice indices created at the top here
    if slice_indices:
        a = as_tensor(a, slice_indices)

    # If any repeated indices were found, apply implicit summation
    # over those
    for i in repeated_indices:
        mi = MultiIndex((i, ))
        a = IndexSum(a, mi)

    # Check for zero (last so we can get indices etc from a, could
    # possibly be done faster by checking early instead)
    if isinstance(self, Zero):
        shape = a.ufl_shape
        fi = a.ufl_free_indices
        fid = a.ufl_index_dimensions
        a = Zero(shape, fi, fid)

    return a
Beispiel #4
0
def as_tensor(expressions, indices=None):
    """UFL operator: Make a tensor valued expression.

    This works in two different ways, by using indices or lists.

    1) Returns :math:`A` such that :math:`A` [*indices*] = *expressions*.
    If *indices* are provided, *expressions* must be a scalar
    valued expression with all the provided indices among
    its free indices. This operator will then map each of these
    indices to a tensor axis, thereby making a tensor valued
    expression from a scalar valued expression with free indices.

    2) Returns :math:`A` such that :math:`A[k,...]` = *expressions*[k].
    If no indices are provided, *expressions* must be a list
    or tuple of expressions. The expressions can also consist
    of recursively nested lists to build higher rank tensors.
    """
    if indices is None:
        # Allow as_tensor(as_tensor(A)) and as_vector(as_vector(v)) in user code
        if isinstance(expressions, Expr):
            return expressions

        # Support numpy array, but avoid importing numpy if not needed
        if not isinstance(expressions, (list, tuple)):
            expressions = from_numpy_to_lists(expressions)

        # Sanity check
        if not isinstance(expressions, (list, tuple)):
            error("Expecting nested list or tuple.")

        # Recursive conversion from nested lists to nested ListTensor
        # objects
        return _as_list_tensor(expressions)
    else:
        # Make sure we have a tuple of indices
        if isinstance(indices, list):
            indices = tuple(indices)
        elif not isinstance(indices, tuple):
            indices = (indices, )

        # Special case for as_tensor(expr, ii) with ii = ()
        if indices == ():
            return expressions

        indices = MultiIndex(indices)

        # Special case for simplification as_tensor(A[ii], ii) -> A
        if isinstance(expressions, Indexed):
            A, ii = expressions.ufl_operands
            if indices.indices() == ii.indices():
                return A

        # Make a tensor from given scalar expression with free indices
        return ComponentTensor(expressions, indices)
Beispiel #5
0
 def __init__(self, gc, i):
     self.scalar = True
     component = (i, )
     shape = gc.ufl_shape
     all_indices, _, _ = create_slice_indices(component, shape,
                                              gc.ufl_free_indices)
     mi = MultiIndex(all_indices)
     Indexed.__init__(self, gc, mi)
     if gc.gf.scalar:
         assert i == 0
         self.__impl__ = gc.gf
         self.gf = gc
     else:
         self.__impl__ = gc.gf[i]
         self.gf = None
Beispiel #6
0
 def multi_index(self, o):
     new_indices = tuple(self.index(i) for i in o.indices())
     return MultiIndex(new_indices)
Beispiel #7
0
def _mult(a, b):
    # Discover repeated indices, which results in index sums
    afi = a.ufl_free_indices
    bfi = b.ufl_free_indices
    afid = a.ufl_index_dimensions
    bfid = b.ufl_index_dimensions
    fi, fid, ri, rid = merge_overlapping_indices(afi, afid, bfi, bfid)

    # Pick out valid non-scalar products here (dot products):
    # - matrix-matrix (A*B, M*grad(u)) => A . B
    # - matrix-vector (A*v) => A . v
    s1, s2 = a.ufl_shape, b.ufl_shape
    r1, r2 = len(s1), len(s2)

    if r1 == 0 and r2 == 0:
        # Create scalar product
        p = Product(a, b)
        ti = ()

    elif r1 == 0 or r2 == 0:
        # Scalar - tensor product
        if r2 == 0:
            a, b = b, a

        # Check for zero, simplifying early if possible
        if isinstance(a, Zero) or isinstance(b, Zero):
            shape = s1 or s2
            return Zero(shape, fi, fid)

        # Repeated indices are allowed, like in:
        # v[i]*M[i,:]

        # Apply product to scalar components
        ti = indices(len(b.ufl_shape))
        p = Product(a, b[ti])

    elif r1 == 2 and r2 in (1, 2):  # Matrix-matrix or matrix-vector
        if ri:
            error("Not expecting repeated indices in non-scalar product.")

        # Check for zero, simplifying early if possible
        if isinstance(a, Zero) or isinstance(b, Zero):
            shape = s1[:-1] + s2[1:]
            return Zero(shape, fi, fid)

        # Return dot product in index notation
        ai = indices(len(a.ufl_shape) - 1)
        bi = indices(len(b.ufl_shape) - 1)
        k = indices(1)

        p = a[ai + k] * b[k + bi]
        ti = ai + bi

    else:
        error("Invalid ranks {0} and {1} in product.".format(r1, r2))

    # TODO: I think applying as_tensor after index sums results in
    # cleaner expression graphs.
    # Wrap as tensor again
    if ti:
        p = as_tensor(p, ti)

    # If any repeated indices were found, apply implicit summation
    # over those
    for i in ri:
        mi = MultiIndex((Index(count=i), ))
        p = IndexSum(p, mi)

    return p
Beispiel #8
0
def compileUFL(form, patch, *args, **kwargs):
    if isinstance(form, Equation):
        form = form.lhs - form.rhs
    if not isinstance(form, Form):
        raise Exception("ufl.Form expected.")
    if len(form.arguments()) < 2:
        raise Exception("ConservationLaw model requires form with at least two arguments.")

    phi_, u_ = form.arguments()

    if phi_.ufl_function_space().scalar:
        phi = TestFunction(phi_.ufl_function_space().toVectorSpace())
        form = replace(form,{phi_:phi[0]})
    else:
        phi = phi_
    if u_.ufl_function_space().scalar:
        u = TrialFunction(u_.ufl_function_space().toVectorSpace())
        form = replace(form,{u_:u[0]})
    else:
        u = u_
    _, coeff_ = extract_arguments_and_coefficients(form)
    coeff_ = set(coeff_)

    # added for dirichlet treatment same as conservationlaw model
    dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)]
    # remove the dirichletBCs
    arg = [arg for arg in args if not isinstance(arg, DirichletBC)]
    for dBC in dirichletBCs:
        _, coeff__ = extract_arguments_and_coefficients(dBC.ufl_value)
        coeff_ |= set(coeff__)
    if patch is not None:
        for a in patch:
            try:
                _, coeff__ = extract_arguments_and_coefficients(a)
                coeff_ |= set(coeff__)
            except:
                pass # a might be a float/int and not a ufl expression

    coeff = {c : c.toVectorCoefficient()[0] for c in coeff_ if len(c.ufl_shape) == 0 and not c.is_cellwise_constant()}
    form = replace(form,coeff)
    for bc in dirichletBCs:
        bc.ufl_value = replace(bc.ufl_value, coeff)
    if patch is not None:
        patch = [a if not isinstance(a, Expr) else replace(a,coeff) for a in patch]

    phi = form.arguments()[0]
    dimRange = phi.ufl_shape[0]

    u = form.arguments()[1]
    du = Grad(u)
    d2u = Grad(du)
    ubar = Coefficient(u.ufl_function_space())
    dubar = Grad(ubar)
    d2ubar = Grad(dubar)
    dimDomain = u.ufl_shape[0]

    x = SpatialCoordinate(form.ufl_cell())

    try:
        field = u.ufl_function_space().field
    except AttributeError:
        field = "double"

    # if exact solution is passed in subtract a(u,.) from the form
    if "exact" in kwargs:
        b = replace(form, {u: as_vector(kwargs["exact"])} )
        form = form - b

    dform = apply_derivatives(derivative(action(form, ubar), ubar, u))

    source, flux, boundarySource = splitUFLForm(form)
    linSource, linFlux, linBoundarySource = splitUFLForm(dform)
    fluxDivergence, _, _ = splitUFLForm(inner(source.as_ufl() - div(flux.as_ufl()), phi) * dx(0))

    # split linNVSource off linSource
    # linSources = splitUFL2(u, du, d2u, linSource)
    # linNVSource = linSources[2]
    # linSource = linSources[0] + linSources[1]

    if patch is not None:
        model = ConservationLawModel(dimDomain, dimRange, u, modelSignature(form,*patch,*args))
    else:
        model = ConservationLawModel(dimDomain, dimRange, u, modelSignature(form,None,*args))
    model._replaceCoeff = coeff

    model.hasNeumanBoundary = not boundarySource.is_zero()

    #expandform = expand_indices(expand_derivatives(expand_compounds(equation.lhs)))
    #if expandform == adjoint(expandform):
    #    model.symmetric = 'true'
    model.field = field

    dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)]
    # deprecated
    # if "dirichlet" in kwargs:
    #     dirichletBCs += [DirichletBC(u.ufl_function_space(), as_vector(value), bndId) for bndId, value in kwargs["dirichlet"].items()]

    uflCoefficients = set(form.coefficients())
    for bc in dirichletBCs:
        _, c = extract_arguments_and_coefficients(bc.ufl_value)
        uflCoefficients |= set(c)
    if patch is not None:
        for a in patch:
            if isinstance(a, Expr):
                _, c = extract_arguments_and_coefficients(a)
                uflCoefficients |= set(c)

    constants = dict()
    coefficients = dict()

    for coefficient in uflCoefficients:
        try:
            name = getattr(coefficient, "name")
        except AttributeError:
            name = str(coefficient)
        if coefficient.is_cellwise_constant():
            try:
                parameter = getattr(coefficient, "parameter")
            except AttributeError:
                parameter = None
            if len(coefficient.ufl_shape) == 0:
                constants[coefficient] = model.addConstant('double', name=name, parameter=parameter)
            elif len(coefficient.ufl_shape) == 1:
                constants[coefficient] = model.addConstant('Dune::FieldVector< double, ' + str(coefficient.ufl_shape[0]) + ' >', name=name, parameter=parameter)
            else:
                Exception('Currently, only scalars and vectors are supported as constants')
        else:
            shape = coefficient.ufl_shape[0]
            try:
                coefficients[coefficient] = model.addCoefficient(
                        shape,
                        coefficient.cppTypeName,
                        name=name,
                        field=coefficient.ufl_function_space().field)
            except AttributeError:
                coefficients[coefficient] = model.addCoefficient(
                        shape,
                        coefficient.cppTypeName,
                        name=name)

    model.coefficients = coefficients
    model.constants = constants

    tempVars = kwargs.get("tempVars", True)

    predefined = {u: model.arg_u, du: model.arg_du, d2u: model.arg_d2u}
    predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
    model.predefineCoefficients(predefined,'x')
    model.source = generateCode(predefined, source, tempVars=tempVars)
    model.flux = generateCode(predefined, flux, tempVars=tempVars)
    predefined.update({ubar: model.arg_ubar, dubar: model.arg_dubar, d2ubar: model.arg_d2ubar})
    model.linSource = generateCode(predefined, linSource, tempVars=tempVars)
    model.linFlux = generateCode(predefined, linFlux, tempVars=tempVars)

    # model.linNVSource = generateCode({u: arg, du: darg, d2u: d2arg, ubar: argbar, dubar: dargbar, d2ubar: d2argbar}, linNVSource, model.coefficients, tempVars)

    predefined = {u: model.arg_u}
    predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
    model.predefineCoefficients(predefined,'x')
    model.alpha = generateCode(predefined, boundarySource, tempVars=tempVars)
    predefined.update({ubar: model.arg_ubar})
    model.linAlpha = generateCode(predefined, linBoundarySource, tempVars=tempVars)

    predefined = {u: model.arg_u, du: model.arg_du, d2u: model.arg_d2u}
    predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
    model.predefineCoefficients(predefined,'x')
    model.fluxDivergence = generateCode(predefined, fluxDivergence, tempVars=tempVars)

    if dirichletBCs:
        model.hasDirichletBoundary = True

        predefined = {}
        predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
        model.predefineCoefficients(predefined,'x')

        maxId = 0
        codeDomains = []
        bySubDomain = dict()
        neuman = []
        for bc in dirichletBCs:
            if bc.subDomain in bySubDomain:
                raise Exception('Multiply defined Dirichlet boundary for subdomain ' + str(bc.subDomain))
            if not isinstance(bc.functionSpace, (FunctionSpace, FiniteElementBase)):
                raise Exception('Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement')
            if isinstance(bc.functionSpace, FunctionSpace) and (bc.functionSpace != u.ufl_function_space()):
                raise Exception('Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet')
            if isinstance(bc.functionSpace, FiniteElementBase) and (bc.functionSpace != u.ufl_element()):
                raise Exception('Cannot handle boundary conditions on subspaces, yet')

            if isinstance(bc.value, list):
                neuman = [i for i, x in enumerate(bc.value) if x == None]
            else:
                neuman = []

            value = ExprTensor(u.ufl_shape)
            for key in value.keys():
                value[key] = Indexed(bc.ufl_value, MultiIndex(tuple(FixedIndex(k) for k in key)))
            if isinstance(bc.subDomain,int):
                bySubDomain[bc.subDomain] = value,neuman
                maxId = max(maxId, bc.subDomain)
            else:
                domain = ExprTensor(())
                for key in domain.keys():
                    domain[key] = Indexed(bc.subDomain, MultiIndex(tuple(FixedIndex(k) for k in key)))
                codeDomains.append( (value,neuman,domain) )
        defaultCode = []
        defaultCode.append(Declaration(Variable('int', 'domainId')))
        defaultCode.append(Declaration(Variable('auto', 'tmp0'),
            initializer=UnformattedExpression('auto','intersection.geometry().center()')))
        for i,v in enumerate(codeDomains):
            block = Block()
            defaultCode.append(
                    generateDirichletDomainCode(predefined, v[2], tempVars=tempVars))
            defaultCode.append('if (domainId)')
            block = UnformattedBlock()
            block.append('std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId+i+1) + ' );')
            if len(v[1])>0:
                [block.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1]]
            block.append('return true;')
            defaultCode.append(block)
        defaultCode.append(return_(False))

        bndId = Variable('const int', 'bndId')
        getBndId = UnformattedExpression('int', 'BoundaryIdProviderType::boundaryId( ' + model.arg_i.name + ' )')
        switch = SwitchStatement(bndId, default=defaultCode)
        for i,v in bySubDomain.items():
            code = []
            if len(v[1])>0:
                [code.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1]]
            code.append(return_(True))
            switch.append(i, code)
        model.isDirichletIntersection = [Declaration(bndId, initializer=getBndId),
                                         UnformattedBlock('std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + bndId.name + ' );'),
                                         switch
                                        ]

        switch = SwitchStatement(model.arg_bndId, default=assign(model.arg_r, construct("RRangeType", 0)))
        for i, v in bySubDomain.items():
            switch.append(i, generateDirichletCode(predefined, v[0], tempVars=tempVars))
        for i,v in enumerate(codeDomains):
            switch.append(i+maxId+1, generateDirichletCode(predefined, v[0], tempVars=tempVars))
        model.dirichlet = [switch]

    return model
Beispiel #9
0
 def multi_index(self, x):
     comp = self._multi_index_values(x)
     return MultiIndex(tuple(FixedIndex(i) for i in comp))
Beispiel #10
0
def _compileUFL(integrands, form, *args, tempVars=True):
    if isinstance(form, Equation):
        form = form.lhs - form.rhs
    if not isinstance(form, Form):
        raise ValueError("ufl.Form or ufl.Equation expected.")

    # added for dirichlet treatment same as conservationlaw model
    dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)]

    uflExpr = [form] + [bc.ufl_value for bc in dirichletBCs]
    if len(form.arguments()) < 2:
        raise ValueError(
            "Integrands model requires form with at least two arguments.")

    x = SpatialCoordinate(form.ufl_cell())
    n = FacetNormal(form.ufl_cell())

    cellVolume = CellVolume(form.ufl_cell())
    maxCellEdgeLength = MaxCellEdgeLength(form.ufl_cell())
    minCellEdgeLength = MinCellEdgeLength(form.ufl_cell())

    facetArea = FacetArea(form.ufl_cell())
    maxFacetEdgeLength = MaxFacetEdgeLength(form.ufl_cell())
    minFacetEdgeLength = MinFacetEdgeLength(form.ufl_cell())

    phi, u = form.arguments()
    ubar = Coefficient(u.ufl_function_space())

    derivatives = gatherDerivatives(form, [phi, u])

    derivatives_phi = derivatives[0]
    derivatives_u = derivatives[1]
    derivatives_ubar = map_expr_dags(Replacer({u: ubar}), derivatives_u)

    try:
        integrands.field = u.ufl_function_space().field
    except AttributeError:
        pass

    integrals = splitForm(form, [phi])

    dform = apply_derivatives(derivative(action(form, ubar), ubar, u))
    linearizedIntegrals = splitForm(dform, [phi, u])

    if not set(
            integrals.keys()) <= {'cell', 'exterior_facet', 'interior_facet'}:
        raise Exception('unknown integral encountered in ' +
                        str(set(integrals.keys())) + '.')

    if 'cell' in integrals.keys():
        arg = Variable(integrands.domainValueTuple, 'u')

        predefined = {
            derivatives_u[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.interior = generateUnaryCode(predefined,
                                                derivatives_phi,
                                                integrals['cell'],
                                                tempVars=tempVars)

        predefined = {
            derivatives_ubar[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.linearizedInterior = generateUnaryLinearizedCode(
            predefined,
            derivatives_phi,
            derivatives_u,
            linearizedIntegrals.get('cell'),
            tempVars=tempVars)

    if 'exterior_facet' in integrals.keys():
        arg = Variable(integrands.domainValueTuple, 'u')

        predefined = {
            derivatives_u[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[n] = integrands.facetNormal('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.boundary = generateUnaryCode(predefined,
                                                derivatives_phi,
                                                integrals['exterior_facet'],
                                                tempVars=tempVars)

        predefined = {
            derivatives_ubar[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[n] = integrands.facetNormal('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.linearizedBoundary = generateUnaryLinearizedCode(
            predefined,
            derivatives_phi,
            derivatives_u,
            linearizedIntegrals.get('exterior_facet'),
            tempVars=tempVars)

    if 'interior_facet' in integrals.keys():
        argIn = Variable(integrands.domainValueTuple, 'uIn')
        argOut = Variable(integrands.domainValueTuple, 'uOut')

        predefined = {
            derivatives_u[i](s): arg[i]
            for i in range(len(derivatives_u))
            for s, arg in (('+', argIn), ('-', argOut))
        }
        predefined[x] = integrands.spatialCoordinate('xIn')
        predefined[n('+')] = integrands.facetNormal('xIn')
        predefined[cellVolume('+')] = integrands.cellVolume('Side::in')
        predefined[cellVolume('-')] = integrands.cellVolume('Side::out')
        predefined[maxCellEdgeLength('+')] = maxEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[maxCellEdgeLength('-')] = maxEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[minCellEdgeLength('+')] = minEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[minCellEdgeLength('-')] = minEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, True)
        integrands.skeleton = generateBinaryCode(predefined,
                                                 derivatives_phi,
                                                 integrals['interior_facet'],
                                                 tempVars=tempVars)

        predefined = {
            derivatives_ubar[i](s): arg[i]
            for i in range(len(derivatives_u))
            for s, arg in (('+', argIn), ('-', argOut))
        }
        predefined[x] = integrands.spatialCoordinate('xIn')
        predefined[n('+')] = integrands.facetNormal('xIn')
        predefined[cellVolume('+')] = integrands.cellVolume('Side::in')
        predefined[cellVolume('-')] = integrands.cellVolume('Side::out')
        predefined[maxCellEdgeLength('+')] = maxEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[maxCellEdgeLength('-')] = maxEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[minCellEdgeLength('+')] = minEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[minCellEdgeLength('-')] = minEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, True)
        integrands.linearizedSkeleton = generateBinaryLinearizedCode(
            predefined,
            derivatives_phi,
            derivatives_u,
            linearizedIntegrals.get('interior_facet'),
            tempVars=tempVars)

    if dirichletBCs:
        integrands.hasDirichletBoundary = True

        predefined = {}
        # predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + integrands.arg_x.name + ' ) )')
        predefined[x] = UnformattedExpression(
            'auto', 'intersection.geometry().center( )')
        integrands.predefineCoefficients(predefined, False)

        maxId = 0
        codeDomains = []
        bySubDomain = dict()
        neuman = []
        wholeDomain = None
        for bc in dirichletBCs:
            if bc.subDomain in bySubDomain:
                raise Exception(
                    'Multiply defined Dirichlet boundary for subdomain ' +
                    str(bc.subDomain))
            if not isinstance(bc.functionSpace,
                              (FunctionSpace, FiniteElementBase)):
                raise Exception(
                    'Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement'
                )
            if isinstance(bc.functionSpace, FunctionSpace) and (
                    bc.functionSpace != u.ufl_function_space()):
                raise Exception(
                    'Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet'
                )
            if isinstance(bc.functionSpace, FiniteElementBase) and (
                    bc.functionSpace != u.ufl_element()):
                raise Exception(
                    'Cannot handle boundary conditions on subspaces, yet')

            if isinstance(bc.value, list):
                neuman = [i for i, x in enumerate(bc.value) if x == None]
            else:
                neuman = []

            value = ExprTensor(u.ufl_shape)
            for key in value.keys():
                value[key] = Indexed(
                    bc.ufl_value,
                    MultiIndex(tuple(FixedIndex(k) for k in key)))
            if bc.subDomain is None:
                wholeDomain = value, neuman
            elif isinstance(bc.subDomain, int):
                bySubDomain[bc.subDomain] = value, neuman
                maxId = max(maxId, bc.subDomain)
            else:
                domain = ExprTensor(())
                for key in domain.keys():
                    domain[key] = Indexed(
                        bc.subDomain,
                        MultiIndex(tuple(FixedIndex(k) for k in key)))
                codeDomains.append((value, neuman, domain))
        defaultCode = []
        if len(codeDomains) > 0:
            defaultCode.append(Declaration(Variable('int', 'domainId')))
        # defaultCode.append(Declaration(Variable('auto', 'x'),
        #     initializer=UnformattedExpression('auto','intersection.geometry().center()')))
        for i, v in enumerate(codeDomains):
            block = Block()
            block.append(
                generateDirichletDomainCode(predefined,
                                            v[2],
                                            tempVars=tempVars))
            block.append('if (domainId)')
            ifBlock = UnformattedBlock()
            ifBlock.append(
                'std::fill( dirichletComponent.begin(), dirichletComponent.end(), '
                + str(maxId + i + 2) + ' );')
            if len(v[1]) > 0:
                [
                    ifBlock.append('dirichletComponent[' + str(c) + '] = 0;')
                    for c in v[1]
                ]
            ifBlock.append('return true;')
            block.append(ifBlock)
            defaultCode.append(block)
        if wholeDomain is not None:
            block = UnformattedBlock()
            block.append(
                'std::fill( dirichletComponent.begin(), dirichletComponent.end(), '
                + str(maxId + 1) + ' );')
            if len(wholeDomain[1]) > 0:
                [
                    block.append('dirichletComponent[' + str(c) + '] = 0;')
                    for c in wholeDomain[1]
                ]
            block.append('return true;')
            defaultCode.append(block)
        defaultCode.append(return_(False))

        bndId = Variable('const int', 'bndId')
        getBndId = UnformattedExpression(
            'int', 'BoundaryIdProviderType::boundaryId( ' +
            integrands.arg_i.name + ' )')
        # getBndId = UnformattedExpression('int', 'boundaryIdGetter_.boundaryId( ' + integrands.arg_i.name + ' )')
        switch = SwitchStatement(bndId, default=defaultCode)
        for i, v in bySubDomain.items():
            code = []
            if len(v[1]) > 0:
                [
                    code.append('dirichletComponent[' + str(c) + '] = 0;')
                    for c in v[1]
                ]
            code.append(return_(True))
            switch.append(i, code)
        integrands.isDirichletIntersection = [
            Declaration(bndId, initializer=getBndId),
            UnformattedBlock(
                'std::fill( dirichletComponent.begin(), dirichletComponent.end(), '
                + bndId.name + ' );'), switch
        ]

        predefined[x] = UnformattedExpression(
            'auto', 'entity().geometry().global( Dune::Fem::coordinate( ' +
            integrands.arg_x.name + ' ) )')
        if wholeDomain is None:
            defaultCode = assign(integrands.arg_r, construct("RRangeType", 0))
        else:
            defaultCode = generateDirichletCode(predefined,
                                                wholeDomain[0],
                                                tempVars=tempVars)
        switch = SwitchStatement(integrands.arg_bndId, default=defaultCode)
        for i, v in bySubDomain.items():
            switch.append(
                i, generateDirichletCode(predefined, v[0], tempVars=tempVars))
        for i, v in enumerate(codeDomains):
            switch.append(
                i + maxId + 2,
                generateDirichletCode(predefined, v[0], tempVars=tempVars))
        integrands.dirichlet = [switch]

    return integrands