Esempio n. 1
0
def ffc_jit(ufl_form, form_compiler_parameters=None):

    # Prepare form compiler parameters with overrides from dolfin and kwargs
    p = ffc.default_jit_parameters()
    p.update(dict(parameters["form_compiler"]))
    p.update(form_compiler_parameters or {})
    return ffc.jit(ufl_form, parameters=p)
Esempio n. 2
0
def ffc_jit(ufl_form, form_compiler_parameters=None):

    # Prepare form compiler parameters with overrides from dolfin and kwargs
    p = ffc.default_jit_parameters()
    p.update(dict(parameters["form_compiler"]))
    p.update(form_compiler_parameters or {})
    return ffc.jit(ufl_form, parameters=p)
Esempio n. 3
0
def element_pair(request):
    """Given a UFL element, returns UFL element and a JIT-compiled and wrapped UFC element."""

    ufl_element = request.param
    ufc_element, ufc_dofmap = ffc.jit(ufl_element, parameters=None)
    ufc_element = ffc_factory.make_ufc_finite_element(ufc_element)
    return ufl_element, ufc_element
Esempio n. 4
0
def element_pair(request):
    """Given a UFL element, returns UFL element and a JIT-compiled and
    wrapped UFC element.

    """

    ufl_element = request.param
    ufc_element, ufc_dofmap = ffc.jit(ufl_element, parameters=None)
    ufc_element = ffc_factory.make_ufc_finite_element(ufc_element)
    return ufl_element, ufc_element
Esempio n. 5
0
def jit(ufl_object, form_compiler_parameters=None, mpi_comm=None):
    """Just-in-time compile any provided UFL Form or FiniteElement using FFC.

    Default parameters from FFC are overridden by parameters["form_compiler"]
    first and then the form_compiler_parameters argument to this function.
    """
    # Check that form is not empty (workaround for bug in UFL where
    # bilinear form 0*u*v*dx becomes the functional 0*dx)
    if isinstance(ufl_object, ufl.Form) and ufl_object.empty():
        cpp.dolfin_error("jit.py", "perform just-in-time compilation of form",
                         "Form is empty. Cannot pass to JIT compiler")

    # Compatibility checks on ffc interface
    if not (hasattr(ffc, 'default_parameters') and hasattr(ffc, 'jit')
            and hasattr(ffc, 'ufc_signature')):
        cpp.dolfin_error(
            "jit.py", "perform just-in-time compilation of form",
            "Form compiler must implement 'default_parameters()', "
            "'jit(ufl_object, parameters=None)' "
            "and 'ufc_signature()' functions")

    # Check DOLFIN build time UFC matches currently loaded UFC
    if cpp.__ufcsignature__ != ffc.ufc_signature():
        cpp.dolfin_error(
            "jit.py", "perform just-in-time compilation of form",
            "DOLFIN was not compiled against matching"
            "UFC from current FFC installation.")

    # Prepare form compiler parameters with overrides from dolfin and kwargs
    p = ffc.default_parameters()
    p.update(parameters["form_compiler"])
    p.update(form_compiler_parameters or {})

    # Execute!
    try:
        result = ffc.jit(ufl_object, parameters=p)
    except Exception as e:
        tb_text = ''.join(traceback.format_exception(*sys.exc_info()))
        cpp.dolfin_error("jit.py", "perform just-in-time compilation of form",
                         "ffc.jit failed with message:\n%s" % (tb_text, ))

    if isinstance(ufl_object, ufl.Form):
        compiled_form, module, prefix = result
        compiled_form = cpp.make_ufc_form(compiled_form)
        return compiled_form, module, prefix
    elif isinstance(ufl_object, ufl.FiniteElementBase):
        ufc_element, ufc_dofmap = result
        ufc_element = cpp.make_ufc_finite_element(ufc_element)
        ufc_dofmap = cpp.make_ufc_dofmap(ufc_dofmap)
        return ufc_element, ufc_dofmap
    elif isinstance(ufl_object, ufl.Mesh):
        ufc_coordinate_mapping = result
        ufc_coordinate_mapping = cpp.make_ufc_coordinate_mapping(
            ufc_coordinate_mapping)
        return ufc_coordinate_mapping
Esempio n. 6
0
    def test_poisson(self):
        "Test that JIT compiler is fast enough."

        # FIXME: Use local cache: cache_dir argument to instant.build_module
        #options = {"log_level": INFO + 5}
        #options = {"log_level": 5}
        options = {"log_level": WARNING}

        # Define two forms with the same signatures
        element = FiniteElement("Lagrange", "triangle", 1)
        v = TestFunction(element)
        u = TrialFunction(element)
        f = Coefficient(element)
        g = Coefficient(element)
        a0 = f*dot(grad(v), grad(u))*dx
        a1 = g*dot(grad(v), grad(u))*dx

        # Strange this needs to be done twice

        # Compile a0 so it will be in the cache (both in-memory and disk)
        jit(a0, options)
        jit(a0, options)

        # Compile a0 again (should be really fast, using in-memory cache)
        t = time()
        jit(a0, options)
        dt0 = time() - t

        # Compile a1 (should be fairly fast, using disk cache)
        t = time()
        jit(a1, options)
        dt1 = time() - t

        # Good values
        dt0_good = 0.005
        dt1_good = 0.01

        print("\nJIT in-memory cache:", dt0)
        print("JIT disk cache:     ", dt1)
        print("Reasonable values are %g and %g" % (dt0_good, dt1_good))

        # Check times
        assert dt0 < 10*dt0_good
        assert dt1 < 10*dt1_good
Esempio n. 7
0
    def _init_from_ufl(self, mesh, element, constrained_domain=None):

        # Initialize the ufl.FunctionSpace first to check for good
        # meaning
        ufl.FunctionSpace.__init__(self, mesh.ufl_domain(), element)

        # Compile dofmap and element
        ufc_element, ufc_dofmap = ffc.jit(element, parameters=None)
        ufc_element = cpp.fem.make_ufc_finite_element(ufc_element)

        # Create DOLFIN element and dofmap
        dolfin_element = cpp.fem.FiniteElement(ufc_element)
        ufc_dofmap = cpp.fem.make_ufc_dofmap(ufc_dofmap)
        if constrained_domain is None:
            dolfin_dofmap = cpp.fem.DofMap(ufc_dofmap, mesh)
        else:
            dolfin_dofmap = cpp.fem.DofMap(ufc_dofmap, mesh,
                                           constrained_domain)

        # Initialize the cpp.FunctionSpace
        self._cpp_object = cpp.function.FunctionSpace(mesh, dolfin_element,
                                                      dolfin_dofmap)
Esempio n. 8
0
    def __init__(self, form, **kwargs):

        # Check form argument
        if not isinstance(form, ufl.Form):
            raise RuntimeError("Expected a ufl.Form.")

        sd = form.subdomain_data()
        self.subdomains, = list(sd.values())  # Assuming single domain
        domain, = list(sd.keys())  # Assuming single domain
        mesh = domain.ufl_cargo()

        # Having a mesh in the form is a requirement
        if mesh is None:
            raise RuntimeError("Expecting to find a Mesh in the form.")

        form_compiler_parameters = kwargs.pop("form_compiler_parameters", None)

        # Add DOLFIN include paths (just the Boost path for special
        # math functions is really required)
        # FIXME: move getting include paths to elsewhere
        import pkgconfig
        d = pkgconfig.parse('dolfin')
        if form_compiler_parameters is None:
            form_compiler_parameters = {"external_include_dirs": d["include_dirs"]}
        else:
            # FIXME: add paths if dict entry already exists
            form_compiler_parameters["external_include_dirs"] = d["include_dirs"]

        ufc_form = ffc.jit(form, form_compiler_parameters)
        ufc_form = cpp.fem.make_ufc_form(ufc_form[0])

        function_spaces = [func.function_space()._cpp_object for func in form.arguments()]

        cpp.fem.Form.__init__(self, ufc_form, function_spaces)

        original_coefficients = form.coefficients()
        self.coefficients = []
        for i in range(self.num_coefficients()):
            j = self.original_coefficient_position(i)
            self.coefficients.append(original_coefficients[j].cpp_object())

        # Type checking coefficients
        if not all(isinstance(c, (cpp.function.GenericFunction))
                   for c in self.coefficients):
            coefficient_error = "Error while extracting coefficients. "
            raise TypeError(coefficient_error +
                            "Either provide a dict of cpp.function.GenericFunctions, " +
                            "or use Function to define your form.")

        for i in range(self.num_coefficients()):
            if isinstance(self.coefficients[i], cpp.function.GenericFunction):
                self.set_coefficient(i, self.coefficients[i])

        # Attach mesh (because function spaces and coefficients may be
        # empty lists)
        if not function_spaces:
            self.set_mesh(mesh)

        # Attach subdomains to C++ Form if we have them
        subdomains = self.subdomains.get("cell")
        if subdomains is not None:
            self.set_cell_domains(subdomains)
        subdomains = self.subdomains.get("exterior_facet")
        if subdomains is not None:
            self.set_exterior_facet_domains(subdomains)
        subdomains = self.subdomains.get("interior_facet")
        if subdomains is not None:
            self.set_interior_facet_domains(subdomains)
        subdomains = self.subdomains.get("vertex")
        if subdomains is not None:
            self.set_vertex_domains(subdomains)
Esempio n. 9
0
def ffc_jit(ufl_form, form_compiler_parameters=None):
    # Prepare form compiler parameters with overrides from dolfin
    p = ffc.default_jit_parameters()
    p["scalar_type"] = "double complex" if common.has_petsc_complex else "double"
    p.update(form_compiler_parameters or {})
    return ffc.jit(ufl_form, parameters=p)