Exemple #1
0
def value_size(obj: ufl.Coefficient) -> Union[List[int], int]:
    if DOLFIN_VERSION_MAJOR >= 2018:
        value_shape = obj.value_shape()
        if len(value_shape) == 0:
            return 1
        return [0]
    return obj.value_size()
Exemple #2
0
    def __init__(self, space, name='x'):
        with PETSc.Log.Stage(name + '_init'):

            Coefficient.__init__(self, space)
            self._name = name
            self.space = space

            with PETSc.Log.Event('create_global'):
                self._vector = self.space.get_composite_da().createGlobalVec()
                self._vector.set(0.0)
                self._activevector = self._vector

            with PETSc.Log.Event('create_local'):
                #create local vectors- one for EACH component on each PATCH
                self._lvectors = []
                for si in xrange(self.space.nspaces):
                    for ci in xrange(self.space.get_space(si).ncomp):
                        for bi in xrange(self.space.get_space(si).npatches):
                            self._lvectors.append(
                                self.space.get_space(si).get_da(
                                    ci, bi).createLocalVector())

            if self.space.nspaces > 1:
                self._split = tuple(
                    SplitFunction(self.space.get_space(i),
                                  name="%s[%d]" % (self.name(), i),
                                  gvec=self._vector,
                                  si=i,
                                  parentspace=self.space)
                    for i in range(self.space.nspaces))
            else:
                self._split = (self, )
def count_flops(n):
    mesh = Mesh(VectorElement('CG', interval, 1))
    tfs = FunctionSpace(mesh, TensorElement('DG', interval, 1, shape=(n, n)))
    vfs = FunctionSpace(mesh, VectorElement('DG', interval, 1, dim=n))

    ensemble_f = Coefficient(vfs)
    ensemble2_f = Coefficient(vfs)
    phi = TestFunction(tfs)

    i, j = indices(2)
    nc = 42  # magic number
    L = ((IndexSum(
        IndexSum(
            Product(nc * phi[i, j], Product(ensemble_f[i], ensemble_f[i])),
            MultiIndex((i, ))), MultiIndex((j, ))) * dx) +
         (IndexSum(
             IndexSum(
                 Product(nc * phi[i, j], Product(
                     ensemble2_f[j], ensemble2_f[j])), MultiIndex(
                         (i, ))), MultiIndex((j, ))) * dx) -
         (IndexSum(
             IndexSum(
                 2 * nc *
                 Product(phi[i, j], Product(ensemble_f[i], ensemble2_f[j])),
                 MultiIndex((i, ))), MultiIndex((j, ))) * dx))

    kernel, = compile_form(L, parameters=dict(mode='spectral'))
    return EstimateFlops().visit(kernel.ast)
Exemple #4
0
def test_expr():
    from ufl import triangle, FiniteElement, TestFunction, TrialFunction, Coefficient
    element = FiniteElement("CG", triangle, 1)
    v = TestFunction(element)
    u = TrialFunction(element)
    f = Coefficient(element)
    g = Coefficient(element)
    expr = (f + g) * u.dx(0) * (g - 1) * v
    return expr
def test_only_first_order(V):
    u = Coefficient(V)

    v = TestFunction(V)

    c = Coefficient(V)

    F = (inner(c, c) * inner(Dt(Dt(u)), v) + inner(grad(u), grad(v)) +
         inner(c, v) + inner(Dt(u), v)) * dx

    with pytest.raises(ValueError):
        check_integrals(F.integrals(), expect_time_derivative=True)
Exemple #6
0
    def set_coefficients(self, integral_data, form_data):
        """Prepare the coefficients of the form.

        :arg integral_data: UFL integral data
        :arg form_data: UFL form data
        """
        coefficients = []
        coefficient_numbers = []
        # enabled_coefficients is a boolean array that indicates which
        # of reduced_coefficients the integral requires.
        for i in range(len(integral_data.enabled_coefficients)):
            if integral_data.enabled_coefficients[i]:
                coefficient = form_data.reduced_coefficients[i]
                if type(coefficient.ufl_element()) == ufl_MixedElement:
                    split = [
                        Coefficient(
                            FunctionSpace(coefficient.ufl_domain(), element))
                        for element in
                        coefficient.ufl_element().sub_elements()
                    ]
                    coefficients.extend(split)
                    self.coefficient_split[coefficient] = split
                else:
                    coefficients.append(coefficient)
                # This is which coefficient in the original form the
                # current coefficient is.
                # Consider f*v*dx + g*v*ds, the full form contains two
                # coefficients, but each integral only requires one.
                coefficient_numbers.append(
                    form_data.original_coefficient_positions[i])
        for i, coefficient in enumerate(coefficients):
            self.coefficient_args.append(
                self._coefficient(coefficient, "w_%d" % i))
        self.kernel.coefficient_numbers = tuple(coefficient_numbers)
Exemple #7
0
def test_pre_and_post_traversal():
    element = FiniteElement("CG", "triangle", 1)
    v = TestFunction(element)
    f = Coefficient(element)
    g = Coefficient(element)
    p1 = f * v
    p2 = g * v
    s = p1 + p2

    # NB! These traversal algorithms are intended to guarantee only
    # parent before child and vice versa, not this particular
    # ordering:
    assert list(pre_traversal(s)) == [s, p2, g, v, p1, f, v]
    assert list(post_traversal(s)) == [g, v, p2, f, v, p1, s]
    assert list(unique_pre_traversal(s)) == [s, p2, g, v, p1, f]
    assert list(unique_post_traversal(s)) == [v, f, p1, g, p2, s]
Exemple #8
0
    def set_cell_sizes(self, domain):
        """Setup a fake coefficient for "cell sizes".

        :arg domain: The domain of the integral.

        This is required for scaling of derivative basis functions on
        physically mapped elements (Argyris, Bell, etc...).  We need a
        measure of the mesh size around each vertex (hence this lives
        in P1).

        Should the domain have topological dimension 0 this does
        nothing.
        """
        if domain.ufl_cell().topological_dimension() > 0:
            # Can't create P1 since only P0 is a valid finite element if
            # topological_dimension is 0 and the concept of "cell size"
            # is not useful for a vertex.
            f = Coefficient(
                FunctionSpace(domain, FiniteElement("P", domain.ufl_cell(),
                                                    1)))
            funarg, expression = prepare_coefficient(
                f,
                "cell_sizes",
                self.scalar_type,
                interior_facet=self.interior_facet)
            self.cell_sizes_arg = funarg
            self._cell_sizes = expression
Exemple #9
0
def test_physically_mapped_facet():
    mesh = Mesh(VectorElement("P", triangle, 1))

    # set up variational problem
    U = FiniteElement("Morley", mesh.ufl_cell(), 2)
    V = FiniteElement("P", mesh.ufl_cell(), 1)
    R = FiniteElement("P", mesh.ufl_cell(), 1)
    Vv = VectorElement(BrokenElement(V))
    Qhat = VectorElement(BrokenElement(V[facet]))
    Vhat = VectorElement(V[facet])
    Z = FunctionSpace(mesh, MixedElement(U, Vv, Qhat, Vhat, R))

    z = Coefficient(Z)
    u, d, qhat, dhat, lam = split(z)

    s = FacetNormal(mesh)
    trans = as_matrix([[1, 0], [0, 1]])
    mat = trans*grad(grad(u))*trans + outer(d, d) * u
    J = (u**2*dx +
         u**3*dx +
         u**4*dx +
         inner(mat, mat)*dx +
         inner(grad(d), grad(d))*dx +
         dot(s, d)**2*ds)
    L_match = inner(qhat, dhat - d)
    L = J + inner(lam, inner(d, d)-1)*dx + (L_match('+') + L_match('-'))*dS + L_match*ds
    compile_form(L)
Exemple #10
0
    def set_coefficients(self, integral_data, form_data):
        """Prepare the coefficients of the form.

        :arg integral_data: UFL integral data
        :arg form_data: UFL form data
        """
        name = "w"
        self.coefficient_args = [
            coffee.Decl(SCALAR_TYPE, coffee.Symbol(name),
                        pointers=[("const",), ()],
                        qualifiers=["const"])
        ]

        # enabled_coefficients is a boolean array that indicates which
        # of reduced_coefficients the integral requires.
        for n in range(len(integral_data.enabled_coefficients)):
            if not integral_data.enabled_coefficients[n]:
                continue

            coeff = form_data.reduced_coefficients[n]
            if type(coeff.ufl_element()) == ufl_MixedElement:
                coeffs = [Coefficient(FunctionSpace(coeff.ufl_domain(), element))
                          for element in coeff.ufl_element().sub_elements()]
                self.coefficient_split[coeff] = coeffs
            else:
                coeffs = [coeff]
            expressions = prepare_coefficients(coeffs, n, name, self.interior_facet)
            self.coefficient_map.update(zip(coeffs, expressions))
def test_can_split_mixed(W):
    u = Coefficient(W)

    v = TestFunction(W)

    c = Coefficient(W)

    F = (inner(c, c) * inner(Dt(u), v) + inner(grad(u), grad(v)) +
         inner(c, v) + inner(Dt(u), v)) * dx

    split = extract_terms(F)

    expect_t = (inner(c, c) * inner(Dt(u), v) + inner(Dt(u), v)) * dx
    expect_no_t = inner(grad(u), grad(v)) * dx + inner(c, v) * dx

    assert sig(expect_t) == sig(split.time)
    assert sig(expect_no_t) == sig(split.remainder)
def test_expecting_time_derivative(V):
    u = Coefficient(V)

    v = TestFunction(V)

    c = Coefficient(V)

    F = (inner(grad(u), grad(v)) + inner(c, v)) * dx

    with pytest.raises(ValueError):
        check_integrals(F.integrals(), expect_time_derivative=True)

    check_integrals(F.integrals(), expect_time_derivative=False)

    F += inner(Dt(u), v) * dx
    with pytest.raises(ValueError):
        check_integrals(F.integrals(), expect_time_derivative=False)
Exemple #13
0
    def set_coordinates(self, domain):
        """Prepare the coordinate field.

        :arg domain: :class:`ufl.Domain`
        """
        # Create a fake coordinate coefficient for a domain.
        f = Coefficient(FunctionSpace(domain, domain.ufl_coordinate_element()))
        self.domain_coordinate[domain] = f
        self.coordinates_arg = self._coefficient(f, "coords")
def test_Dt_linear(V, typ):
    u = Coefficient(V)

    v = TestFunction(V)

    c = Coefficient(V)

    F = (inner(grad(u), grad(v)) + inner(c, v) + inner(Dt(u), v)) * dx

    if typ == "mul":
        F += inner(Dt(u), c) * inner(Dt(u), v) * dx
    elif typ == "div":
        F += inner(Dt(u), v) / Dt(u)[0] * dx
    elif typ == "sin":
        F += inner(sin(Dt(u)[0]), v[0]) * dx

    with pytest.raises(ValueError):
        check_integrals(F.integrals(), expect_time_derivative=True)
Exemple #15
0
def HodgeLaplaceGradCurl(element, felement):
    tau, v = TestFunctions(element)
    sigma, u = TrialFunctions(element)
    f = Coefficient(felement)

    a = (inner(tau, sigma) - inner(grad(tau), u) + inner(v, grad(sigma)) +
         inner(curl(v), curl(u))) * dx
    L = inner(v, f) * dx

    return a, L
Exemple #16
0
def codeDG(self):
    code = self._code()

    u = self.trialFunction
    ubar = Coefficient(u.ufl_function_space())
    penalty = self.penalty
    if penalty is None:
        penalty = 1
    if isinstance(penalty, Expr):
        if penalty.ufl_shape == ():
            penalty = as_vector([penalty])
        try:
            penalty = expand_indices(
                expand_derivatives(expand_compounds(penalty)))
        except:
            pass
        assert penalty.ufl_shape == u.ufl_shape
        dmPenalty = as_vector([
            replace(
                expand_derivatives(diff(replace(penalty, {u: ubar}),
                                        ubar))[i, i], {ubar: u})
            for i in range(u.ufl_shape[0])
        ])
    else:
        dmPenalty = None

    code.append(AccessModifier("public"))
    x = SpatialCoordinate(self.space.cell())
    predefined = {}
    self.predefineCoefficients(predefined, x)
    spatial = Variable('const auto', 'y')
    predefined.update({
        x:
        UnformattedExpression(
            'auto', 'entity().geometry().global( Dune::Fem::coordinate( x ) )')
    })
    generateMethod(code,
                   penalty,
                   'RRangeType',
                   'penalty',
                   args=['const Point &x', 'const DRangeType &u'],
                   targs=['class Point', 'class DRangeType'],
                   static=False,
                   const=True,
                   predefined=predefined)
    generateMethod(code,
                   dmPenalty,
                   'RRangeType',
                   'linPenalty',
                   args=['const Point &x', 'const DRangeType &u'],
                   targs=['class Point', 'class DRangeType'],
                   static=False,
                   const=True,
                   predefined=predefined)
    return code
def test_can_split_mixed_split(W):
    u = Coefficient(W)
    from ufl import split as splt
    u0, u1 = splt(u)

    v = TestFunction(W)
    v0, v1 = splt(v)

    c = Coefficient(W)

    F = (inner(c, c) * inner(Dt(u0), v0) + inner(grad(u), grad(v)) +
         inner(c, v) + inner(Dt(u), v)) * dx

    split = extract_terms(F)

    expect_t = (inner(c, c) * inner(Dt(u0), v0) + inner(Dt(u), v)) * dx
    expect_no_t = inner(grad(u), grad(v)) * dx + inner(c, v) * dx

    assert sig(expect_t) == sig(split.time)
    assert sig(expect_no_t) == sig(split.remainder)
Exemple #18
0
    def set_cell_sizes(self, domain):
        """Setup a fake coefficient for "cell sizes".

        :arg domain: The domain of the integral.

        This is required for scaling of derivative basis functions on
        physically mapped elements (Argyris, Bell, etc...).  We need a
        measure of the mesh size around each vertex (hence this lives
        in P1).
        """
        f = Coefficient(FunctionSpace(domain, FiniteElement("P", domain.ufl_cell(), 1)))
        funarg, expression = prepare_coefficient(f, "cell_sizes", self.scalar_type, interior_facet=self.interior_facet)
        self.cell_sizes_arg = funarg
        self._cell_sizes = expression
    def initialize_data(self):
        """
        Extract required objects for defining error control
        forms. This will be stored, reused and in particular named.
        """
        # Developer's note: The UFL-FFC-DOLFIN--PyDOLFIN toolchain for
        # error control is quite fine-tuned. In particular, the order
        # of coefficients in forms is (and almost must be) used for
        # their assignment. This means that the order in which these
        # coefficients are defined matters and should be considered
        # fixed.

        from ufl import FiniteElement, Coefficient
        from ufl.algorithms.elementtransformations import tear, increase_order

        # Primal trial element space
        self._V = self.u.element()

        # Primal test space == Dual trial space
        Vhat = self.weak_residual.arguments()[0].element()

        # Discontinuous version of primal trial element space
        self._dV = tear(self._V)

        # Extract domain and geometric dimension
        domain, = self._V.domains()
        gdim = domain.geometric_dimension()

        # Coefficient representing improved dual
        E = increase_order(Vhat)
        self._Ez_h = Coefficient(E)
        self.ec_names[id(self._Ez_h)] = "__improved_dual"

        # Coefficient representing cell bubble function
        B = FiniteElement("B", domain, gdim + 1)
        self._b_T = Coefficient(B)
        self.ec_names[id(self._b_T)] = "__cell_bubble"

        # Coefficient representing strong cell residual
        self._R_T = Coefficient(self._dV)
        self.ec_names[id(self._R_T)] = "__cell_residual"

        # Coefficient representing cell cone function
        C = FiniteElement("DG", domain, gdim)
        self._b_e = Coefficient(C)
        self.ec_names[id(self._b_e)] = "__cell_cone"

        # Coefficient representing strong facet residual
        self._R_dT = Coefficient(self._dV)
        self.ec_names[id(self._R_dT)] = "__facet_residual"

        # Define discrete dual on primal test space
        self._z_h = Coefficient(Vhat)
        self.ec_names[id(self._z_h)] = "__discrete_dual_solution"

        # Piecewise constants for assembling indicators
        self._DG0 = FiniteElement("DG", domain, 0)
Exemple #20
0
def test_remove_complex_nodes(self):
    cell = triangle
    element = FiniteElement("Lagrange", cell, 1)

    u = TrialFunction(element)
    v = TestFunction(element)
    f = Coefficient(element)

    a = conj(v)
    b = real(u)
    c = imag(f)
    d = conj(real(v))*imag(conj(u))

    assert remove_complex_nodes(a) == v
    assert remove_complex_nodes(b) == u
    with pytest.raises(ufl.log.UFLException):
        remove_complex_nodes(c)
    with pytest.raises(ufl.log.UFLException):
        remove_complex_nodes(d)
Exemple #21
0
def test_delta_elimination(mode):
    # Code sample courtesy of Marco Morandini:
    # https://github.com/firedrakeproject/tsfc/issues/182
    scheme = "default"
    degree = 3

    element_lambda = FiniteElement("Quadrature",
                                   tetrahedron,
                                   degree,
                                   quad_scheme=scheme)
    element_eps_p = VectorElement("Quadrature",
                                  tetrahedron,
                                  degree,
                                  dim=6,
                                  quad_scheme=scheme)

    element_chi_lambda = MixedElement(element_eps_p, element_lambda)

    chi_lambda = Coefficient(element_chi_lambda)
    delta_chi_lambda = TestFunction(element_chi_lambda)

    L = inner(delta_chi_lambda, chi_lambda) * dx(degree=degree, scheme=scheme)
    kernel, = compile_form(L, parameters={'mode': mode})
Exemple #22
0
#
# UFL is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# UFL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with UFL. If not, see <http://www.gnu.org/licenses/>.
#
# Modified by Martin Sandve Alnæs, 2009
#
# Last changed: 2009-03-02
#
# The bilinear form a(v, u) and linear form L(v) for Poisson's equation.
from ufl import (Coefficient, FiniteElement, TestFunction, TrialFunction, dx,
                 grad, inner, triangle)

element = FiniteElement("Lagrange", triangle, 1)

u = TrialFunction(element)
v = TestFunction(element)
f = Coefficient(element)

a = inner(grad(v), grad(u)) * dx(degree=1)
L = v * f * dx(degree=2)
Exemple #23
0
def prepare_input_arguments(forms, object_names, reserved_objects):
    """
    Extract required input arguments to UFLErrorControlGenerator.

    *Arguments*

        forms (tuple)
            Three (linear case) or two (nonlinear case) forms
            specifying the primal problem and the goal

        object_names (dict)
            Map from object ids to object names

        reserved_names (dict)
            Map from reserved object names to object ids

    *Returns*

        tuple (of length 3) containing

        Form or tuple
            A single linear form or a tuple of a bilinear and a linear
            form

        Form
            A linear form or a functional for the goal functional

        Coefficient
            The coefficient considered as the unknown
    """

    # Check that we get a tuple of forms
    expecting_tuple_msg = "Expecting tuple of forms, got %s" % str(forms)
    assert(isinstance(forms, (list, tuple))), expecting_tuple_msg

    def __is_nonlinear(forms):
        return len(forms) == 2

    def __is_linear(forms):
        return len(forms) == 3

    # Extract Coefficient labelled as 'unknown'
    u = reserved_objects.get("unknown", None)

    if __is_nonlinear(forms):
        (F, M) = forms

        # Check that unknown is defined
        assert (u), "Can't extract 'unknown'. The Coefficient representing the unknown must be labelled by 'unknown' for nonlinear problems."

        # Check that forms have the expected rank
        assert(len(F.arguments()) == 1)
        assert(len(M.arguments()) == 0)

        # Return primal, goal and unknown
        return (F, M, u)

    elif __is_linear(forms):
        # Throw error if unknown is given, don't quite know what to do
        # with this case yet
        if u:
            error("'unknown' defined: not implemented for linear problems")

        (a, L, M) = forms

        # Check that forms have the expected rank
        arguments = a.arguments()
        assert(len(arguments) == 2)
        assert(len(L.arguments()) == 1)
        assert(len(M.arguments()) == 1)

        # Standard case: create default Coefficient in trial space and
        # label it __discrete_primal_solution
        V = arguments[1].element()
        u = Coefficient(V)
        object_names[id(u)] = "__discrete_primal_solution"

        return ((a, L), M, u)

    else:
        error("Wrong input tuple length: got %s, expected 2 or 3-tuple"
              % str(forms))
Exemple #24
0
#
# Implemented by imitation of
#  http://code.google.com/p/debiosee/wiki/DemosOptiocFlowHornSchunck
# but not tested so this could contain errors!
#
from ufl import (Coefficient, Constant, FiniteElement, VectorElement,
                 derivative, dot, dx, grad, inner, triangle)

# Finite element spaces for scalar and vector fields
cell = triangle
S = FiniteElement("CG", cell, 1)
V = VectorElement("CG", cell, 1)

# Optical flow function
u = Coefficient(V)

# Previous image brightness
I0 = Coefficient(S)

# Current image brightness
I1 = Coefficient(S)

# Regularization parameter
lamda = Constant(cell)

# Coefficiental to minimize
M = (dot(u, grad(I1)) + (I1 - I0))**2 * dx\
    + lamda * inner(grad(u), grad(u)) * dx

# Derived linear system
L = derivative(M, u)
Exemple #25
0
coord_element = VectorElement("Lagrange", triangle, 1)
mesh = Mesh(coord_element)

# Function Space
element = FiniteElement("Lagrange", triangle, 2)
V = FunctionSpace(mesh, element)

# Trial and test functions
u = TrialFunction(V)
v = TestFunction(V)

# Define a constant RHS
f = Constant(V)

# Define the bilinear and linear forms according to the
# variational formulation of the equations::
a = inner(grad(u), grad(v)) * dx
L = inner(f, v) * dx

# Define linear form representing the action of the form "a" on
# the coefficient "ui"
ui = Coefficient(V)
M = action(a, ui)

# Define form to compute the L2 norm of the error
usol = Coefficient(V)
uexact = Coefficient(V)
E = inner(usol - uexact, usol - uexact) * dx

forms = [M, L, E]
Exemple #26
0
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with UFL. If not, see <http://www.gnu.org/licenses/>.
#
# Modified by Martin Sandve Alnes, 2009
#
# Last changed: 2009-01-12
#
# The bilinear form a(v, u) and linear form L(v) for
# a mixed formulation of Poisson's equation with BDM
# (Brezzi-Douglas-Marini) elements.
#
from ufl import (Coefficient, FiniteElement, TestFunctions, TrialFunctions,
                 div, dot, dx, triangle)

cell = triangle
BDM1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1)
DG0 = FiniteElement("Discontinuous Lagrange", cell, 0)

element = BDM1 * DG0

(tau, w) = TestFunctions(element)
(sigma, u) = TrialFunctions(element)

f = Coefficient(DG0)

a = (dot(tau, sigma) - div(tau) * u + w * div(sigma)) * dx
L = w * f * dx
# Copyright (C) 2005-2007 Anders Logg
#
# This file is part of UFL.
#
# UFL is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# UFL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with UFL. If not, see <http://www.gnu.org/licenses/>.
#
# The bilinear form a(v, u) and linear form L(v) for
# tensor-weighted Poisson's equation.
from ufl import (Coefficient, FiniteElement, TensorElement, TestFunction,
                 TrialFunction, dx, grad, inner, triangle)

P1 = FiniteElement("Lagrange", triangle, 1)
P0 = TensorElement("Discontinuous Lagrange", triangle, 0, shape=(2, 2))

v = TestFunction(P1)
u = TrialFunction(P1)
C = Coefficient(P0)

a = inner(grad(v), C * grad(u)) * dx
Exemple #28
0
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with UFL. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2008-03-31
# Last changed: 2008-03-31
#
# The linearised bilinear form a(u,v) and linear form L(v) for
# the nonlinear equation - div (1+u) grad u = f (non-linear Poisson)
from ufl import (Coefficient, FiniteElement, TestFunction, TrialFunction,
                 VectorElement, dot, dx, grad, i, triangle)

element = FiniteElement("Lagrange", triangle, 2)

QE = FiniteElement("Quadrature", triangle, 2, quad_scheme="default")
sig = VectorElement("Quadrature", triangle, 1, quad_scheme="default")

v = TestFunction(element)
u = TrialFunction(element)
u0 = Coefficient(element)
C = Coefficient(QE)
sig0 = Coefficient(sig)
f = Coefficient(element)

a = v.dx(i) * C * u.dx(i) * dx(
    metadata={"quadrature_degree": 2}) + v.dx(i) * 2 * u0 * u * u0.dx(i) * dx
L = v * f * dx - dot(grad(v), sig0) * dx(metadata={"quadrature_degree": 1})
Exemple #29
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
Exemple #30
0
 def form(cell, degree):
     m = Mesh(VectorElement('CG', cell, 1))
     V = FunctionSpace(m, VectorElement('CG', cell, degree))
     f = Coefficient(V)
     return div(f) * dx