Exemple #1
0
def _analyze_form(form, parameters):
    "Analyze form, returning form data."

    # Check that form is not empty
    ffc_assert(not form.empty(),
               "Form (%s) seems to be zero: cannot compile it." % str(form))

    # Compute form metadata
    if parameters["representation"] == "uflacs":
        # Temporary workaround to let uflacs have a different preprocessing pipeline
        # than the legacy representations quadrature and tensor. This approach imposes
        # a limitation that e.g. uflacs and tensor representation cannot be mixed in the same form.
        from ufl.classes import Jacobian
        form_data = compute_form_data(form,
                                      do_apply_function_pullbacks=True,
                                      do_apply_integral_scaling=True,
                                      do_apply_geometry_lowering=True,
                                      preserve_geometry_types=(Jacobian,),
                                      do_apply_restrictions=True,
                                      )
    else:
        form_data = compute_form_data(form)

    info("")
    info(str(form_data))

    # Attach integral meta data
    _attach_integral_metadata(form_data, parameters)

    return form_data
Exemple #2
0
def _analyze_form(form, parameters):
    "Analyze form, returning form data."

    # Check that form is not empty
    if form.empty():
        error("Form (%s) seems to be zero: cannot compile it." % str(form))

    # Hack to override representation with environment variable
    forced_r = os.environ.get("FFC_FORCE_REPRESENTATION")
    if forced_r:
        warning(
            "representation:    forced by $FFC_FORCE_REPRESENTATION to '%s'" %
            forced_r)
        r = forced_r
    else:
        # Check representation parameters to figure out how to
        # preprocess
        r = _extract_representation_family(form, parameters)
    debug("Preprocessing form using '%s' representation family." % r)

    # Compute form metadata
    if r == "uflacs":
        # Temporary workaround to let uflacs have a different
        # preprocessing pipeline than the legacy quadrature
        # representation. This approach imposes a limitation that,
        # e.g. uflacs and qudrature, representations cannot be mixed
        # in the same form.
        from ufl.classes import Jacobian
        form_data = compute_form_data(form,
                                      do_apply_function_pullbacks=True,
                                      do_apply_integral_scaling=True,
                                      do_apply_geometry_lowering=True,
                                      preserve_geometry_types=(Jacobian, ),
                                      do_apply_restrictions=True)
    elif r == "tsfc":
        try:
            # TSFC provides compute_form_data wrapper using correct
            # kwargs
            from tsfc.ufl_utils import compute_form_data as tsfc_compute_form_data
        except ImportError:
            error(
                "Failed to import tsfc.ufl_utils.compute_form_data when asked "
                "for tsfc representation.")
        form_data = tsfc_compute_form_data(form)
    elif r == "quadrature":
        # quadrature representation
        form_data = compute_form_data(form)
    else:
        error("Unexpected representation family '%s' for form preprocessing." %
              r)

    info("")
    info(str(form_data))

    # Attach integral meta data
    _attach_integral_metadata(form_data, r, parameters)
    _validate_representation_choice(form_data, r)

    return form_data
Exemple #3
0
def assertEqualBySampling(actual, expected):
    ad = compute_form_data(actual * dx)
    a = ad.preprocessed_form.integrals_by_type("cell")[0].integrand()
    bd = compute_form_data(expected * dx)
    b = bd.preprocessed_form.integrals_by_type("cell")[0].integrand()

    assert ([
        ad.function_replace_map[ac] for ac in ad.reduced_coefficients
    ] == [bd.function_replace_map[bc] for bc in bd.reduced_coefficients])

    n = ad.num_coefficients

    def make_value(c):
        if isinstance(c, Coefficient):
            z = 0.3
            m = c.count()
        else:
            z = 0.7
            m = c.number()
        if c.ufl_shape == ():
            return z * (0.1 + 0.9 * m / n)
        elif len(c.ufl_shape) == 1:
            return tuple(
                (z * (j + 0.1 + 0.9 * m / n) for j in range(c.ufl_shape[0])))
        else:
            raise NotImplementedError(
                "Tensor valued expressions not supported here.")

    amapping = dict((c, make_value(c)) for c in chain(
        ad.original_form.coefficients(), ad.original_form.arguments()))
    bmapping = dict((c, make_value(c)) for c in chain(
        bd.original_form.coefficients(), bd.original_form.arguments()))

    acell = actual.ufl_domain().ufl_cell()
    bcell = expected.ufl_domain().ufl_cell()
    assert acell == bcell
    if acell.geometric_dimension() == 1:
        x = (0.3, )
    elif acell.geometric_dimension() == 2:
        x = (0.3, 0.4)
    elif acell.geometric_dimension() == 3:
        x = (0.3, 0.4, 0.5)
    av = a(x, amapping)
    bv = b(x, bmapping)

    if not av == bv:
        print("Tried to sample expressions to compare but failed:")
        print()
        print((str(a)))
        print(av)
        print()
        print((str(b)))
        print(bv)
        print()

    assert av == bv
Exemple #4
0
def _analyze_form(form, parameters):
    "Analyze form, returning form data."

    # Check that form is not empty
    if form.empty():
        error("Form (%s) seems to be zero: cannot compile it." % str(form))

    # Hack to override representation with environment variable
    forced_r = os.environ.get("FFC_FORCE_REPRESENTATION")
    if forced_r:
        warning("representation:    forced by $FFC_FORCE_REPRESENTATION to '%s'" % forced_r)
        r = forced_r
    else:
        # Check representation parameters to figure out how to
        # preprocess
        r = _extract_representation_family(form, parameters)
    debug("Preprocessing form using '%s' representation family." % r)

    # Compute form metadata
    if r == "uflacs":
        # Temporary workaround to let uflacs have a different
        # preprocessing pipeline than the legacy quadrature
        # representation. This approach imposes a limitation that,
        # e.g. uflacs and qudrature, representations cannot be mixed
        # in the same form.
        from ufl.classes import Jacobian
        form_data = compute_form_data(form,
                                      do_apply_function_pullbacks=True,
                                      do_apply_integral_scaling=True,
                                      do_apply_geometry_lowering=True,
                                      preserve_geometry_types=(Jacobian,),
                                      do_apply_restrictions=True)
    elif r == "tsfc":
        try:
            # TSFC provides compute_form_data wrapper using correct
            # kwargs
            from tsfc.ufl_utils import compute_form_data as tsfc_compute_form_data
        except ImportError:
            error("Failed to import tsfc.ufl_utils.compute_form_data when asked "
                  "for tsfc representation.")
        form_data = tsfc_compute_form_data(form)
    elif r == "quadrature":
        # quadrature representation
        form_data = compute_form_data(form)
    else:
        error("Unexpected representation family '%s' for form preprocessing." % r)

    info("")
    info(str(form_data))

    # Attach integral meta data
    _attach_integral_metadata(form_data, r, parameters)
    _validate_representation_choice(form_data, r)

    return form_data
Exemple #5
0
def assertEqualBySampling(actual, expected):
    ad = compute_form_data(actual*dx)
    a = ad.preprocessed_form.integrals_by_type("cell")[0].integrand()
    bd = compute_form_data(expected*dx)
    b = bd.preprocessed_form.integrals_by_type("cell")[0].integrand()

    assert ([ad.function_replace_map[ac] for ac in ad.reduced_coefficients]
            == [bd.function_replace_map[bc] for bc in bd.reduced_coefficients])

    n = ad.num_coefficients

    def make_value(c):
        if isinstance(c, Coefficient):
            z = 0.3
            m = c.count()
        else:
            z = 0.7
            m = c.number()
        if c.ufl_shape == ():
            return z * (0.1 + 0.9 * m / n)
        elif len(c.ufl_shape) == 1:
            return tuple((z * (j + 0.1 + 0.9 * m / n) for j in range(c.ufl_shape[0])))
        else:
            raise NotImplementedError("Tensor valued expressions not supported here.")

    amapping = dict((c, make_value(c)) for c in chain(ad.original_form.coefficients(), ad.original_form.arguments()))
    bmapping = dict((c, make_value(c)) for c in chain(bd.original_form.coefficients(), bd.original_form.arguments()))

    acell = actual.ufl_domain().ufl_cell()
    bcell = expected.ufl_domain().ufl_cell()
    assert acell == bcell
    if acell.geometric_dimension() == 1:
        x = (0.3,)
    elif acell.geometric_dimension() == 2:
        x = (0.3, 0.4)
    elif acell.geometric_dimension() == 3:
        x = (0.3, 0.4, 0.5)
    av = a(x, amapping)
    bv = b(x, bmapping)

    if not av == bv:
        print("Tried to sample expressions to compare but failed:")
        print()
        print((str(a)))
        print(av)
        print()
        print((str(b)))
        print(bv)
        print()

    assert av == bv
Exemple #6
0
def test_segregated_derivative_of_convection(self):
    cell = tetrahedron
    V = FiniteElement("CG", cell, 1)
    W = VectorElement("CG", cell, 1)

    u = Coefficient(W)
    v = Coefficient(W)
    du = TrialFunction(V)
    dv = TestFunction(V)

    L = dot(dot(u, nabla_grad(u)), v)

    Lv = {}
    Lvu = {}
    for i in range(cell.geometric_dimension()):
        Lv[i] = derivative(L, v[i], dv)
        for j in range(cell.geometric_dimension()):
            Lvu[i, j] = derivative(Lv[i], u[j], du)

    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            form = Lvu[i, j]*dx
            fd = compute_form_data(form)
            pf = fd.preprocessed_form
            a = expand_indices(pf)
            # print (i,j), str(a)

    k = Index()
    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            actual = Lvu[i, j]
            expected = du*u[i].dx(j)*dv + u[k]*du.dx(k)*dv
            assertEqualBySampling(actual, expected)
Exemple #7
0
def test_segregated_derivative_of_convection(self):
    cell = tetrahedron
    V = FiniteElement("CG", cell, 1)
    W = VectorElement("CG", cell, 1)

    u = Coefficient(W)
    v = Coefficient(W)
    du = TrialFunction(V)
    dv = TestFunction(V)

    L = dot(dot(u, nabla_grad(u)), v)

    Lv = {}
    Lvu = {}
    for i in range(cell.geometric_dimension()):
        Lv[i] = derivative(L, v[i], dv)
        for j in range(cell.geometric_dimension()):
            Lvu[i, j] = derivative(Lv[i], u[j], du)

    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            form = Lvu[i, j]*dx
            fd = compute_form_data(form)
            pf = fd.preprocessed_form
            a = expand_indices(pf)
            # print (i,j), str(a)

    k = Index()
    for i in range(cell.geometric_dimension()):
        for j in range(cell.geometric_dimension()):
            actual = Lvu[i, j]
            expected = du*u[i].dx(j)*dv + u[k]*du.dx(k)*dv
            assertEqualBySampling(actual, expected)
Exemple #8
0
def test_vector_coefficient_derivatives_of_product(self):
    V = VectorElement("Lagrange", triangle, 1)
    VV = TensorElement("Lagrange", triangle, 1)

    dv = TestFunction(V)

    df = Coefficient(VV, count=0)
    g = Coefficient(V, count=1)
    dg = Coefficient(VV, count=2)
    f = Coefficient(V, count=3)
    u = Coefficient(V, count=4)
    cd = {f: df, g: dg}

    integrand = f[i]*g[i]

    i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
    expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0] +\
        f[i0]*as_tensor(dg[i4, i3]*dv[i3], (i4,))[i0]

    F = integrand*dx
    J = derivative(F, u, dv, cd)
    fd = compute_form_data(J)
    actual = fd.preprocessed_form.integrals()[0].integrand()

    # Tricky case! These are equal in representation except
    # that the outermost sum/indexsum are swapped.
    # Sampling the expressions instead of comparing representations.
    x = (0, 0)
    funcs = {dv: (13, 14), f: (1, 2), g: (3, 4), df: ((5, 6), (7, 8)), dg: ((9, 10), (11, 12))}
    self.assertEqual(replace(actual, fd.function_replace_map)(x, funcs), expected(x, funcs))
Exemple #9
0
    def __init__(self, form, name, parameters):
        """A wrapper object for one or more FFC kernels compiled from a given :class:`~Form`.

        :arg form: the :class:`~Form` from which to compile the kernels.
        :arg name: a prefix to be applied to the compiled kernel names. This is primarily useful for debugging.
        :arg parameters: a dict of parameters to pass to the form compiler.
        """
        if self._initialized:
            return

        incl = PreprocessNode('#include "firedrake_geometry.h"\n')
        inc = [path.dirname(__file__)]
        try:
            ffc_tree = ffc_compile_form(form, prefix=name, parameters=parameters)
            kernels = []
            # need compute_form_data here to get preproc form integrals
            fd = compute_form_data(form)
            elements = fd.elements
            needs_orientations = self._needs_orientations(elements)
            for it, kernel in zip(fd.preprocessed_form.integrals(), ffc_tree):
                # Set optimization options
                opts = {} if it.integral_type() not in ['cell'] else default_parameters["coffee"]
                kernels.append((Kernel(Root([incl, kernel]), '%s_%s_integral_0_%s' %
                                       (name, it.integral_type(), it.subdomain_id()), opts, inc),
                                needs_orientations))
            self.kernels = tuple(kernels)
            self._empty = False
        except EmptyIntegrandError:
            # FFC noticed that the integrand was zero and simplified
            # it, catch this here and set a flag telling us to ignore
            # the kernel when returning it in compile_form
            self._empty = True
        self._initialized = True
Exemple #10
0
def test_vector_coefficient_derivatives_of_product(self):
    V = VectorElement("Lagrange", triangle, 1)
    VV = TensorElement("Lagrange", triangle, 1)

    dv = TestFunction(V)

    df = Coefficient(VV, count=0)
    g = Coefficient(V, count=1)
    dg = Coefficient(VV, count=2)
    f = Coefficient(V, count=3)
    u = Coefficient(V, count=4)
    cd = {f: df, g: dg}

    integrand = f[i]*g[i]

    i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
    expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0] +\
        f[i0]*as_tensor(dg[i4, i3]*dv[i3], (i4,))[i0]

    F = integrand*dx
    J = derivative(F, u, dv, cd)
    fd = compute_form_data(J)
    actual = fd.preprocessed_form.integrals()[0].integrand()

    # Tricky case! These are equal in representation except
    # that the outermost sum/indexsum are swapped.
    # Sampling the expressions instead of comparing representations.
    x = (0, 0)
    funcs = {dv: (13, 14), f: (1, 2), g: (3, 4), df: ((5, 6), (7, 8)), dg: ((9, 10), (11, 12))}
    self.assertEqual(replace(actual, fd.function_replace_map)(x, funcs), expected(x, funcs))
Exemple #11
0
def ufl2unicode(expression):
    "Generate Unicode string for a UFL expression or form."
    if isinstance(expression, Form):
        form_data = compute_form_data(expression)
        preprocessed_form = form_data.preprocessed_form
        return form2unicode(preprocessed_form, form_data)
    else:
        return expression2unicode(expression)
Exemple #12
0
def ufl2unicode(expression):
    "Generate Unicode string for a UFL expression or form."
    if isinstance(expression, Form):
        form_data = compute_form_data(expression)
        preprocessed_form = form_data.preprocessed_form
        return form2unicode(preprocessed_form, form_data)
    else:
        return expression2unicode(expression)
Exemple #13
0
def valid_forms(forms_list):
    forms = []
    form_datas = []
    for f in forms_list:
        fd = None
        try:
            fd = compute_form_data(f)
        except:
            fd = None
        if fd is not None:
            forms.append(f)
            form_datas.append(fd)
    return forms, form_datas
Exemple #14
0
def testFormData():

    element = FiniteElement("Lagrange", "tetrahedron", 3)

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

    a = v * u * dx

    form_data = compute_form_data(a)

    form_data_pickle = pickle.dumps(form_data, p)
    form_data_restore = pickle.loads(form_data_pickle)

    assert(str(form_data) == str(form_data_restore))
Exemple #15
0
def testFormData():

    element = FiniteElement("Lagrange", "tetrahedron", 3)

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

    a = v * u * dx

    form_data = compute_form_data(a)

    form_data_pickle = pickle.dumps(form_data, p)
    form_data_restore = pickle.loads(form_data_pickle)

    assert (str(form_data) == str(form_data_restore))
Exemple #16
0
def test_index_simplification_handles_repeated_indices(self):
    mesh = Mesh(VectorElement("P", quadrilateral, 1))
    V = FunctionSpace(mesh, TensorElement("DQ", quadrilateral, 0))
    K = JacobianInverse(mesh)
    G = outer(Identity(2), Identity(2))
    i, j, k, l, m, n = indices(6)
    A = as_tensor(K[m, i] * K[n, j] * G[i, j, k, l], (m, n, k, l))
    i, j = indices(2)
    # Can't use A[i, i, j, j] because UFL automagically index-sums
    # repeated indices in the __getitem__ call.
    Adiag = Indexed(A, MultiIndex((i, i, j, j)))
    A = as_tensor(Adiag, (i, j))
    v = TestFunction(V)
    f = inner(A, v)*dx
    fd = compute_form_data(f, do_apply_geometry_lowering=True)
    integral, = fd.preprocessed_form.integrals()
    assert integral.integrand().ufl_free_indices == ()
Exemple #17
0
def _analyze_form(form, parameters):
    "Analyze form, returning form data."

    # Check that form is not empty
    ffc_assert(not form.empty(),
               "Form (%s) seems to be zero: cannot compile it." % str(form))

    # Compute form metadata
    form_data = compute_form_data(form)

    info("")
    info(str(form_data))

    # Attach integral meta data
    _attach_integral_metadata(form_data, parameters)

    return form_data
Exemple #18
0
def test_everywhere_integrals_with_backwards_compatibility():
    D = Mesh(triangle)

    V = FunctionSpace(D, FiniteElement("CG", triangle, 1))
    f = Coefficient(V)

    a = f * dx
    ida, = compute_form_data(a).integral_data

    # Check some integral data
    assert ida.integral_type == "cell"
    assert ida.subdomain_id == "otherwise"
    assert ida.metadata == {}

    # Integrands are not equal because of renumbering
    itg1 = ida.integrals[0].integrand()
    itg2 = a.integrals()[0].integrand()
    assert type(itg1) == type(itg2)
    assert itg1.ufl_element() == itg2.ufl_element()
Exemple #19
0
def test_everywhere_integrals_with_backwards_compatibility():
    D = Mesh(triangle)

    V = FunctionSpace(D, FiniteElement("CG", triangle, 1))
    f = Coefficient(V)

    a = f * dx
    ida, = compute_form_data(a).integral_data

    # Check some integral data
    assert ida.integral_type == "cell"
    assert ida.subdomain_id == "otherwise"
    assert ida.metadata == {}

    # Integrands are not equal because of renumbering
    itg1 = ida.integrals[0].integrand()
    itg2 = a.integrals()[0].integrand()
    assert type(itg1) == type(itg2)
    assert itg1.ufl_element() == itg2.ufl_element()
Exemple #20
0
def test_coefficient_derivatives(self):
    V = FiniteElement("Lagrange", triangle, 1)

    dv = TestFunction(V)

    f = Coefficient(V, count=0)
    g = Coefficient(V, count=1)
    df = Coefficient(V, count=2)
    dg = Coefficient(V, count=3)
    u = Coefficient(V, count=4)
    cd = {f: df, g: dg}

    integrand = inner(f, g)
    expected = (df*dv)*g + f*(dg*dv)

    F = integrand*dx
    J = derivative(F, u, dv, cd)
    fd = compute_form_data(J)
    actual = fd.preprocessed_form.integrals()[0].integrand()
    assert (actual*dx).signature() == (expected*dx).signature()
    self.assertEqual(replace(actual, fd.function_replace_map), expected)
Exemple #21
0
def test_coefficient_derivatives(self):
    V = FiniteElement("Lagrange", triangle, 1)

    dv = TestFunction(V)

    f = Coefficient(V, count=0)
    g = Coefficient(V, count=1)
    df = Coefficient(V, count=2)
    dg = Coefficient(V, count=3)
    u = Coefficient(V, count=4)
    cd = {f: df, g: dg}

    integrand = inner(f, g)
    expected = (df*dv)*g + f*(dg*dv)

    F = integrand*dx
    J = derivative(F, u, dv, cd)
    fd = compute_form_data(J)
    actual = fd.preprocessed_form.integrals()[0].integrand()
    assert (actual*dx).signature() == (expected*dx).signature()
    self.assertEqual(replace(actual, fd.function_replace_map), expected)
Exemple #22
0
    def __init__(self, form, name, parameters):
        """A wrapper object for one or more FFC kernels compiled from a given :class:`~ufl.classes.Form`.

        :arg form: the :class:`~ufl.classes.Form` from which to compile the kernels.
        :arg name: a prefix to be applied to the compiled kernel names. This is primarily useful for debugging.
        :arg parameters: a dict of parameters to pass to the form compiler.
        """
        if self._initialized:
            return

        incl = [PreprocessNode('#include "firedrake_geometry.h"\n')]
        inc = [path.dirname(__file__)]
        try:
            ffc_tree = ffc_compile_form(form,
                                        prefix=name,
                                        parameters=parameters)
            if len(ffc_tree) == 0:
                raise EmptyIntegrandError
            kernels = []
            # need compute_form_data here to get preproc form integrals
            fd = compute_form_data(form)
            elements = fd.unique_elements
            needs_orientations = self._needs_orientations(elements)
            for it, kernel in zip(fd.preprocessed_form.integrals(), ffc_tree):
                # Set optimization options
                opts = default_parameters["coffee"]
                _kernel = kernel if not parameters.get(
                    "assemble_inverse", False) else _inverse(kernel)
                kernels.append((Kernel(
                    Root(incl + [_kernel]), '%s_%s_integral_0_%s' %
                    (name, it.integral_type(), it.subdomain_id()), opts,
                    inc), needs_orientations))
            self.kernels = tuple(kernels)
            self._empty = False
        except EmptyIntegrandError:
            # FFC noticed that the integrand was zero and simplified
            # it, catch this here and set a flag telling us to ignore
            # the kernel when returning it in compile_form
            self._empty = True
        self._initialized = True
Exemple #23
0
def test_vector_coefficient_derivatives(self):
    V = VectorElement("Lagrange", triangle, 1)
    VV = TensorElement("Lagrange", triangle, 1)

    dv = TestFunction(V)

    df = Coefficient(VV, count=0)
    g = Coefficient(V, count=1)
    f = Coefficient(V, count=2)
    u = Coefficient(V, count=3)
    cd = {f: df}

    integrand = inner(f, g)

    i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
    expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0]

    F = integrand*dx
    J = derivative(F, u, dv, cd)
    fd = compute_form_data(J)
    actual = fd.preprocessed_form.integrals()[0].integrand()
    assert (actual*dx).signature() == (expected*dx).signature()
Exemple #24
0
def test_vector_coefficient_derivatives(self):
    V = VectorElement("Lagrange", triangle, 1)
    VV = TensorElement("Lagrange", triangle, 1)

    dv = TestFunction(V)

    df = Coefficient(VV, count=0)
    g = Coefficient(V, count=1)
    f = Coefficient(V, count=2)
    u = Coefficient(V, count=3)
    cd = {f: df}

    integrand = inner(f, g)

    i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
    expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0]

    F = integrand*dx
    J = derivative(F, u, dv, cd)
    fd = compute_form_data(J)
    actual = fd.preprocessed_form.integrals()[0].integrand()
    assert (actual*dx).signature() == (expected*dx).signature()
Exemple #25
0
def testHyperElasticity(self):
    cell = interval
    element = FiniteElement("CG", cell, 2)
    w = Coefficient(element)
    v = TestFunction(element)
    u = TrialFunction(element)
    b = Constant(cell)
    K = Constant(cell)

    dw = w.dx(0)
    dv = v.dx(0)
    du = v.dx(0)

    E = dw + dw**2 / 2
    E = variable(E)
    Q = b*E**2
    psi = K*(exp(Q)-1)

    f = psi*dx
    F = derivative(f, w, v)
    J = derivative(F, w, u)

    form_data_f = compute_form_data(f)
    form_data_F = compute_form_data(F)
    form_data_J = compute_form_data(J)

    f = form_data_f.preprocessed_form
    F = form_data_F.preprocessed_form
    J = form_data_J.preprocessed_form

    f_expression = strip_variables(f.integrals_by_type("cell")[0].integrand())
    F_expression = strip_variables(F.integrals_by_type("cell")[0].integrand())
    J_expression = strip_variables(J.integrals_by_type("cell")[0].integrand())

    # classes = set(c.__class__ for c in post_traversal(f_expression))

    Kv = .2
    bv = .3
    dw = .5
    dv = .7
    du = .11
    E = dw + dw**2 / 2.
    Q = bv*E**2
    expQ = float(exp(Q))
    psi = Kv*(expQ-1)
    fv = psi
    Fv = 2*Kv*bv*E*(1+dw)*expQ*dv
    Jv = 2*Kv*bv*expQ*dv*du*(E + (1+dw)**2*(2*bv*E**2 + 1))

    def Nv(x, derivatives):
        assert derivatives == (0,)
        return dv

    def Nu(x, derivatives):
        assert derivatives == (0,)
        return du

    def Nw(x, derivatives):
        assert derivatives == (0,)
        return dw

    mapping = {K: Kv, b: bv, w: Nw}
    fv2 = f_expression((0,), mapping)
    self.assertAlmostEqual(fv, fv2)

    v, = form_data_F.original_form.arguments()
    mapping = {K: Kv, b: bv, v: Nv, w: Nw}
    Fv2 = F_expression((0,), mapping)
    self.assertAlmostEqual(Fv, Fv2)

    v, u = form_data_J.original_form.arguments()
    mapping = {K: Kv, b: bv, v: Nv, u: Nu, w: Nw}
    Jv2 = J_expression((0,), mapping)
    self.assertAlmostEqual(Jv, Jv2)
Exemple #26
0
def compile_form(form, name, parameters=None):
    """Compile a form using FFC.

    :arg form: the :class:`ufl.Form` to compile.
    :arg name: a prefix for the generated kernel functions.
    :arg parameters: optional dict of parameters to pass to the form
         compiler. If not provided, parameters are read from the
         :data:`form_compiler` slot of the Firedrake
         :data:`~.parameters` dictionary (which see).

    Returns a tuple of tuples of
    (index, integral type, subdomain id, coordinates, coefficients, needs_orientations, :class:`Kernels <pyop2.op2.Kernel>`).

    ``needs_orientations`` indicates whether the form requires cell
    orientation information (for correctly pulling back to reference
    elements on embedded manifolds).

    The coordinates are extracted from the UFL
    :class:`~ufl.domain.Domain` of the integral.

    """

    # Check that we get a Form
    if not isinstance(form, Form):
        raise RuntimeError("Unable to convert object to a UFL form: %s" % repr(form))

    if parameters is None:
        parameters = default_parameters["form_compiler"]
    else:
        # Override defaults with user-specified values
        _ = parameters
        parameters = default_parameters["form_compiler"].copy()
        parameters.update(_)
    # We stash the compiled kernels on the form so we don't have to recompile
    # if we assemble the same form again with the same optimisations
    if hasattr(form, "_kernels"):
        # Save both kernels and FFC params so we can tell if this
        # cached version is valid (the FFC parameters might have changed)
        kernels, params = form._kernels
        if kernels[0][-1]._opts == default_parameters["coffee"] and \
           kernels[0][-1].name.startswith(name) and \
           params == parameters:
            return kernels

    # need compute_form_data since we use preproc. form integrals later
    fd = compute_form_data(form)

    # If there is no mixed element involved, return the kernels FFC produces
    if all(isinstance(e, (FiniteElement, VectorElement)) for e in fd.unique_sub_elements):
        kernels = [((0, 0),
                    it.integral_type(), it.subdomain_id(),
                    it.domain().data().coordinates,
                    fd.preprocessed_form.coefficients(), needs_orientations, kernel)
                   for it, (kernel, needs_orientations) in zip(fd.preprocessed_form.integrals(),
                                                               FFCKernel(form, name,
                                                                         parameters).kernels)]
        form._kernels = (kernels, parameters)
        return kernels
    # Otherwise pre-split the form into mixed blocks before calling FFC
    kernels = []
    for forms in FormSplitter().split(form):
        for (i, j), f in forms:
            ffc_kernel = FFCKernel(f, name + str(i) + str(j), parameters)
            # FFC noticed the integrand was zero, so don't bother
            # using this kernel (it's invalid anyway)
            if ffc_kernel._empty:
                continue
            ((kernel, needs_orientations), ) = ffc_kernel.kernels
            # need compute_form_data here to get preproc integrals
            fd = compute_form_data(f)
            it = fd.preprocessed_form.integrals()[0]
            kernels.append(((i, j),
                            it.integral_type(),
                            it.subdomain_id(),
                            it.domain().data().coordinates,
                            fd.preprocessed_form.coefficients(),
                            needs_orientations, kernel))
    form._kernels = (kernels, parameters)
    return kernels
Exemple #27
0
 def assertEqualAfterPreprocessing(self, a, b):
     a2 = compute_form_data(a*dx).preprocessed_form
     b2 = compute_form_data(b*dx).preprocessed_form
     self.assertEqual(a2, b2)
Exemple #28
0
def testHyperElasticity(self):
    cell = interval
    element = FiniteElement("CG", cell, 2)
    w = Coefficient(element)
    v = TestFunction(element)
    u = TrialFunction(element)
    b = Constant(cell)
    K = Constant(cell)

    dw = w.dx(0)
    dv = v.dx(0)
    du = v.dx(0)

    E = dw + dw**2 / 2
    E = variable(E)
    Q = b*E**2
    psi = K*(exp(Q)-1)

    f = psi*dx
    F = derivative(f, w, v)
    J = derivative(F, w, u)

    form_data_f = compute_form_data(f)
    form_data_F = compute_form_data(F)
    form_data_J = compute_form_data(J)

    f = form_data_f.preprocessed_form
    F = form_data_F.preprocessed_form
    J = form_data_J.preprocessed_form

    f_expression = strip_variables(f.integrals_by_type("cell")[0].integrand())
    F_expression = strip_variables(F.integrals_by_type("cell")[0].integrand())
    J_expression = strip_variables(J.integrals_by_type("cell")[0].integrand())

    # classes = set(c.__class__ for c in post_traversal(f_expression))

    Kv = .2
    bv = .3
    dw = .5
    dv = .7
    du = .11
    E = dw + dw**2 / 2.
    Q = bv*E**2
    expQ = float(exp(Q))
    psi = Kv*(expQ-1)
    fv = psi
    Fv = 2*Kv*bv*E*(1+dw)*expQ*dv
    Jv = 2*Kv*bv*expQ*dv*du*(E + (1+dw)**2*(2*bv*E**2 + 1))

    def Nv(x, derivatives):
        assert derivatives == (0,)
        return dv

    def Nu(x, derivatives):
        assert derivatives == (0,)
        return du

    def Nw(x, derivatives):
        assert derivatives == (0,)
        return dw

    w, b, K = form_data_f.original_form.coefficients()
    mapping = {K: Kv, b: bv, w: Nw}
    fv2 = f_expression((0,), mapping)
    self.assertAlmostEqual(fv, fv2)

    w, b, K = form_data_F.original_form.coefficients()
    v, = form_data_F.original_form.arguments()
    mapping = {K: Kv, b: bv, v: Nv, w: Nw}
    Fv2 = F_expression((0,), mapping)
    self.assertAlmostEqual(Fv, Fv2)

    w, b, K = form_data_J.original_form.coefficients()
    v, u = form_data_J.original_form.arguments()
    mapping = {K: Kv, b: bv, v: Nv, u: Nu, w: Nw}
    Jv2 = J_expression((0,), mapping)
    self.assertAlmostEqual(Jv, Jv2)
Exemple #29
0
def compile_form(form, name, parameters=None, inverse=False):
    """Compile a form using FFC.

    :arg form: the :class:`~ufl.classes.Form` to compile.
    :arg name: a prefix for the generated kernel functions.
    :arg parameters: optional dict of parameters to pass to the form
         compiler. If not provided, parameters are read from the
         ``form_compiler`` slot of the Firedrake
         :data:`~.parameters` dictionary (which see).
    :arg inverse: If True then assemble the inverse of the local tensor.

    Returns a tuple of tuples of
    (index, integral type, subdomain id, coordinates, coefficients, needs_orientations, :class:`Kernels <pyop2.op2.Kernel>`).

    ``needs_orientations`` indicates whether the form requires cell
    orientation information (for correctly pulling back to reference
    elements on embedded manifolds).

    The coordinates are extracted from the domain of the integral (a
    :func:`~.Mesh`)

    """

    # Check that we get a Form
    if not isinstance(form, Form):
        raise RuntimeError("Unable to convert object to a UFL form: %s" %
                           repr(form))

    if parameters is None:
        parameters = default_parameters["form_compiler"].copy()
    else:
        # Override defaults with user-specified values
        _ = parameters
        parameters = default_parameters["form_compiler"].copy()
        parameters.update(_)

    # We stash the compiled kernels on the form so we don't have to recompile
    # if we assemble the same form again with the same optimisations
    if "firedrake_kernels" in form._cache:
        # Save both kernels and FFC params so we can tell if this
        # cached version is valid (the FFC parameters might have changed)
        kernels, params = form._cache["firedrake_kernels"]
        if kernels[0][-1]._opts == default_parameters["coffee"] and \
           kernels[0][-1].name.startswith(name) and \
           params == parameters:
            return kernels

    # need compute_form_data since we use preproc. form integrals later
    fd = compute_form_data(form)

    # If there is no mixed element involved, return the kernels FFC produces
    # Note: using type rather than isinstance because UFL's VectorElement,
    # TensorElement and OPVectorElement all inherit from MixedElement
    if not any(type(e) is MixedElement for e in fd.unique_sub_elements):
        kernels = [((0, 0), it.integral_type(), it.ufl_domain(),
                    form.subdomain_data()[it.ufl_domain()][it.integral_type()],
                    it.subdomain_id(), fd.preprocessed_form.coefficients(),
                    needs_orientations, kernel)
                   for it, (kernel, needs_orientations
                            ) in zip(fd.preprocessed_form.integrals(),
                                     FFCKernel(form, name, parameters).kernels)
                   ]
        form._cache["firedrake_kernels"] = (kernels, parameters)
        return kernels
    # Otherwise pre-split the form into mixed blocks before calling FFC
    kernels = []
    for forms in FormSplitter().split(form):
        for (i, j), f in forms:
            ffc_kernel = FFCKernel(f, name + str(i) + str(j), parameters)
            # FFC noticed the integrand was zero, so don't bother
            # using this kernel (it's invalid anyway)
            if ffc_kernel._empty:
                continue
            ((kernel, needs_orientations), ) = ffc_kernel.kernels
            # need compute_form_data here to get preproc integrals
            fd = compute_form_data(f)
            it = fd.preprocessed_form.integrals()[0]
            kernels.append(((i, j), it.integral_type(), it.ufl_domain(),
                            it.subdomain_data(), it.subdomain_id(),
                            fd.preprocessed_form.coefficients(),
                            needs_orientations, kernel))
    form._cache["firedrake_kernels"] = (kernels, parameters)
    return kernels
Exemple #30
0
def _test_grad_div_curl_properties(self, cell):
    d = cell.geometric_dimension()

    S = FiniteElement("CG", cell, 1)
    V = VectorElement("CG", cell, 1)
    T = TensorElement("CG", cell, 1)

    cs = Constant(cell)
    cv = VectorConstant(cell)
    ct = TensorConstant(cell)

    s = Coefficient(S)
    v = Coefficient(V)
    t = Coefficient(T)

    def eval_s(x, derivatives=()):
        return sum(derivatives)

    def eval_v(x, derivatives=()):
        return tuple(float(k)+sum(derivatives) for k in range(d))

    def eval_t(x, derivatives=()):
        return tuple(tuple(float(i*j)+sum(derivatives)
                           for i in range(d))
                     for j in range(d))

    mapping = {cs: eval_s, s: eval_s,
               cv: eval_v, v: eval_v,
               ct: eval_t, t: eval_t, }
    x = tuple(1.0+float(k) for k in range(d))

    assert s.ufl_shape == ()
    assert v.ufl_shape == (d,)
    assert t.ufl_shape == (d, d)

    assert cs.ufl_shape == ()
    assert cv.ufl_shape == (d,)
    assert ct.ufl_shape == (d, d)

    self.assertEqual(s(x, mapping=mapping), eval_s(x))
    self.assertEqual(v(x, mapping=mapping), eval_v(x))
    self.assertEqual(t(x, mapping=mapping), eval_t(x))

    assert grad(s).ufl_shape == (d,)
    assert grad(v).ufl_shape == (d, d)
    assert grad(t).ufl_shape == (d, d, d)

    assert grad(cs).ufl_shape == (d,)
    assert grad(cv).ufl_shape == (d, d)
    assert grad(ct).ufl_shape == (d, d, d)

    self.assertEqual(grad(s)[0](x, mapping=mapping), eval_s(x, (0,)))
    self.assertEqual(grad(v)[d-1, d-1](x, mapping=mapping),
                     eval_v(x, derivatives=(d-1,))[d-1])
    self.assertEqual(grad(t)[d-1, d-1, d-1](x, mapping=mapping),
                     eval_t(x, derivatives=(d-1,))[d-1][d-1])

    assert div(grad(cs)).ufl_shape == ()
    assert div(grad(cv)).ufl_shape == (d,)
    assert div(grad(ct)).ufl_shape == (d, d)

    assert s.dx(0).ufl_shape == ()
    assert v.dx(0).ufl_shape == (d,)
    assert t.dx(0).ufl_shape == (d, d)

    assert s.dx(0 == 0).ufl_shape, ()
    assert v.dx(0 == 0).ufl_shape, (d,)
    assert t.dx(0 == 0).ufl_shape, (d, d)

    i, j = indices(2)
    assert s.dx(i).ufl_shape == ()
    assert v.dx(i).ufl_shape == (d,)
    assert t.dx(i).ufl_shape == (d, d)

    assert s.dx(i).ufl_free_indices == (i.count(),)
    assert v.dx(i).ufl_free_indices == (i.count(),)
    assert t.dx(i).ufl_free_indices == (i.count(),)

    self.assertEqual(s.dx(i, j).ufl_shape, ())
    self.assertEqual(v.dx(i, j).ufl_shape, (d,))
    self.assertEqual(t.dx(i, j).ufl_shape, (d, d))

    self.assertTrue(s.dx(i, j).ufl_free_indices == tuple(sorted([i.count(), j.count()])))
    self.assertTrue(v.dx(i, j).ufl_free_indices == tuple(sorted([i.count(), j.count()])))
    self.assertTrue(t.dx(i, j).ufl_free_indices == tuple(sorted([i.count(), j.count()])))

    a0 = s.dx(0)*dx
    a1 = s.dx(0)**2*dx
    a2 = v.dx(0)**2*dx
    a3 = t.dx(0)**2*dx

    a4 = inner(grad(s), grad(s))*dx
    a5 = inner(grad(v), grad(v))*dx
    a6 = inner(grad(t), grad(t))*dx

    a7 = inner(div(grad(s)), s)*dx
    a8 = inner(div(grad(v)), v)*dx
    a9 = inner(div(grad(t)), t)*dx

    fd0 = compute_form_data(a0)
    fd1 = compute_form_data(a1)
    fd2 = compute_form_data(a2)
    fd3 = compute_form_data(a3)

    fd4 = compute_form_data(a4)
    fd5 = compute_form_data(a5)
    fd6 = compute_form_data(a6)

    fd7 = compute_form_data(a7)
    fd8 = compute_form_data(a8)
    fd9 = compute_form_data(a9)
Exemple #31
0
 def assertEqualAfterPreprocessing(self, a, b):
     a2 = compute_form_data(a * dx).preprocessed_form
     b2 = compute_form_data(b * dx).preprocessed_form
     self.assertEqual(a2, b2)