Esempio n. 1
0
def compute_shapes(form: ufl.Form):
    """Computes the shapes of the cell tensor, coefficient & coordinate arrays for a form"""

    # Cell tensor
    elements = tuple(arg.ufl_element() for arg in form.arguments())
    fiat_elements = (create_element(element) for element in elements)
    element_dims = tuple(fe.space_dimension() for fe in fiat_elements)
    A_shape = element_dims

    # Coefficient arrays
    ws_shapes = []
    for coefficient in form.coefficients():
        w_element = coefficient.ufl_element()
        w_dim = create_element(w_element).space_dimension()
        ws_shapes.append((w_dim,))
    if len(ws_shapes) > 0:
        max_w_dim = sorted(ws_shapes, key=lambda w_dim: np.prod(w_dim))[-1]
        w_full_shape = (len(ws_shapes), ) + max_w_dim
    else:
        w_full_shape = (0,)

    # Coordinate dofs array
    num_vertices_per_cell = form.ufl_cell().num_vertices()
    gdim = form.ufl_cell().geometric_dimension()
    coords_shape = (num_vertices_per_cell, gdim)

    return A_shape, w_full_shape, coords_shape
Esempio n. 2
0
    def __init__(self, form: ufl.Form, form_compiler_parameters: dict = {}, jit_parameters: dict = {}):
        """Create dolfinx Form

        Parameters
        ----------
        form
            Pure UFL form
        form_compiler_parameters
            See :py:func:`ffcx_jit <dolfinx.jit.ffcx_jit>`
        jit_parameters
            See :py:func:`ffcx_jit <dolfinx.jit.ffcx_jit>`

        Note
        ----
        This wrapper for UFL form is responsible for the actual FFCX compilation
        and attaching coefficients and domains specific data to the underlying
        C++ Form.
        """

        # Extract subdomain data from 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()
        if mesh is None:
            raise RuntimeError("Expecting to find a Mesh in the form.")

        # Compile UFL form with JIT
        ufc_form = jit.ffcx_jit(
            mesh.mpi_comm(),
            form,
            form_compiler_parameters=form_compiler_parameters,
            jit_parameters=jit_parameters)

        # For every argument in form extract its function space
        function_spaces = [
            func.ufl_function_space()._cpp_object for func in form.arguments()
        ]

        # Prepare coefficients data. For every coefficient in form take
        # its C++ object.
        original_coefficients = form.coefficients()
        coeffs = [original_coefficients[ufc_form.original_coefficient_position(
            i)]._cpp_object for i in range(ufc_form.num_coefficients)]

        # Create dictionary of of subdomain markers (possible None for
        # some dimensions
        subdomains = {cpp.fem.IntegralType.cell: self._subdomains.get("cell"),
                      cpp.fem.IntegralType.exterior_facet: self._subdomains.get("exterior_facet"),
                      cpp.fem.IntegralType.interior_facet: self._subdomains.get("interior_facet"),
                      cpp.fem.IntegralType.vertex: self._subdomains.get("vertex")}

        # Prepare dolfinx.cpp.fem.Form and hold it as a member
        ffi = cffi.FFI()
        self._cpp_object = cpp.fem.create_form(ffi.cast("uintptr_t", ufc_form),
                                               function_spaces, coeffs,
                                               [c._cpp_object for c in form.constants()], subdomains, mesh)
Esempio n. 3
0
def compile_terminal_form(tensor,
                          prefix=None,
                          tsfc_parameters=None,
                          coffee=True):
    """Compiles the TSFC form associated with a Slate :class:`Tensor`
    object. This function will return a :class:`ContextKernel`
    which stores information about the original tensor, integral types
    and the corresponding TSFC kernels.

    :arg tensor: A Slate `Tensor`.
    :arg prefix: An optional `string` indicating the prefix for the
                 subkernel.
    :arg tsfc_parameters: An optional `dict` of parameters to provide
                          TSFC.

    Returns: A `ContextKernel` containing all relevant information.
    """

    assert isinstance(
        tensor,
        Tensor), ("Only terminal tensors have forms associated with them!")
    # Sets a default name for the subkernel prefix.
    # NOTE: the builder will choose a prefix independent of
    # the tensor name for code idempotency reasons, but is not
    # strictly required.
    prefix = prefix or "subkernel%s_" % tensor.__str__()
    mapper = RemoveRestrictions()
    integrals = map(partial(map_integrand_dags, mapper),
                    tensor.form.integrals())

    transformed_integrals = transform_integrals(integrals)
    cxt_kernels = []
    for orig_it_type, integrals in transformed_integrals.items():
        subkernel_prefix = prefix + "%s_to_" % orig_it_type
        form = Form(integrals)
        kernels = tsfc_compile(form,
                               subkernel_prefix,
                               parameters=tsfc_parameters,
                               coffee=coffee,
                               split=False)
        if kernels:
            cxt_k = ContextKernel(tensor=tensor,
                                  coefficients=form.coefficients(),
                                  original_integral_type=orig_it_type,
                                  tsfc_kernels=kernels)
            cxt_kernels.append(cxt_k)

    cxt_kernels = tuple(cxt_kernels)

    return cxt_kernels
Esempio n. 4
0
    def __init__(self, form: ufl.Form, form_compiler_parameters: dict = None):
        """Create dolfin Form

        Parameters
        ----------
        form
            Pure UFL form
        form_compiler_parameters
            Parameters used in JIT FFC compilation of this form

        Note
        ----
        This wrapper for UFL form is responsible for the actual FFC compilation
        and attaching coefficients and domains specific data to the underlying
        C++ Form.
        """
        self.form_compiler_parameters = form_compiler_parameters

        # Extract subdomain data from 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()

        # Compile UFL form with JIT
        ufc_form = jit.ffc_jit(
            form,
            form_compiler_parameters=self.form_compiler_parameters,
            mpi_comm=mesh.mpi_comm())

        # Cast compiled library to pointer to ufc_form
        ffi = cffi.FFI()
        ufc_form = fem.dofmap.make_ufc_form(ffi.cast("uintptr_t", ufc_form))

        # For every argument in form extract its function space
        function_spaces = [
            func.function_space()._cpp_object for func in form.arguments()
        ]

        # Prepare dolfin.Form and hold it as a member
        self._cpp_object = cpp.fem.create_form(ufc_form, function_spaces)

        # Need to fill the form with coefficients data
        # For every coefficient in form take its CPP object
        original_coefficients = form.coefficients()
        for i in range(self._cpp_object.num_coefficients()):
            j = self._cpp_object.original_coefficient_position(i)
            self._cpp_object.set_coefficient(
                i, original_coefficients[j]._cpp_object)

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

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

        # Attach subdomains to C++ Form if we have them
        subdomains = self._subdomains.get("cell")
        if subdomains:
            self._cpp_object.set_cell_domains(subdomains)

        subdomains = self._subdomains.get("exterior_facet")
        if subdomains:
            self._cpp_object.set_exterior_facet_domains(subdomains)

        subdomains = self._subdomains.get("interior_facet")
        if subdomains:
            self._cpp_object.set_interior_facet_domains(subdomains)

        subdomains = self._subdomains.get("vertex")
        if subdomains:
            self._cpp_object.set_vertex_domains(subdomains)
Esempio n. 5
0
    def __init__(self, form: ufl.Form, form_compiler_parameters: dict = None):
        """Create dolfin Form

        Parameters
        ----------
        form
            Pure UFL form
        form_compiler_parameters
            Parameters used in JIT FFC compilation of this form

        Note
        ----
        This wrapper for UFL form is responsible for the actual FFC compilation
        and attaching coefficients and domains specific data to the underlying
        C++ Form.
        """
        self.form_compiler_parameters = form_compiler_parameters

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

        # Extract subdomain data from 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()

        # Compile UFL form with JIT
        ufc_form = jit.ffc_jit(
            form,
            form_compiler_parameters=self.form_compiler_parameters,
            mpi_comm=mesh.mpi_comm())
        # Cast compiled library to pointer to ufc_form
        ufc_form = fem.dofmap.make_ufc_form(ufc_form[0])

        # For every argument in form extract its function space
        function_spaces = [
            func.function_space()._cpp_object for func in form.arguments()
        ]

        # Prepare dolfin.Form and hold it as a member
        self._cpp_object = cpp.fem.Form(ufc_form, function_spaces)

        # Need to fill the form with coefficients data
        # For every coefficient in form take its CPP object
        original_coefficients = form.coefficients()
        for i in range(self._cpp_object.num_coefficients()):
            j = self._cpp_object.original_coefficient_position(i)
            self._cpp_object.set_coefficient(
                j, original_coefficients[i]._cpp_object)

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

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

        # Attach subdomains to C++ Form if we have them
        subdomains = self._subdomains.get("cell")
        self._cpp_object.set_cell_domains(subdomains)

        subdomains = self._subdomains.get("exterior_facet")
        self._cpp_object.set_exterior_facet_domains(subdomains)

        subdomains = self._subdomains.get("interior_facet")
        self._cpp_object.set_interior_facet_domains(subdomains)

        subdomains = self._subdomains.get("vertex")
        self._cpp_object.set_vertex_domains(subdomains)
Esempio n. 6
0
    def __init__(self, form: ufl.Form, form_compiler_parameters: dict = {}, jit_parameters: dict = {}):
        """Create dolfinx Form

        Parameters
        ----------
        form
            Pure UFL form
        form_compiler_parameters
            Parameters used in FFCX compilation of this form. Run `ffcx --help` in the commandline
            to see all available options.
        jit_parameters
            Parameters controlling JIT compilation of C code.

        Note
        ----
        This wrapper for UFL form is responsible for the actual FFCX compilation
        and attaching coefficients and domains specific data to the underlying
        C++ Form.
        """

        # Extract subdomain data from 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()

        # Compile UFL form with JIT
        ufc_form = jit.ffcx_jit(
            form,
            form_compiler_parameters=form_compiler_parameters,
            jit_parameters=jit_parameters,
            mpi_comm=mesh.mpi_comm())

        # For every argument in form extract its function space
        function_spaces = [
            func.ufl_function_space()._cpp_object for func in form.arguments()
        ]

        # Prepare dolfinx.Form and hold it as a member
        ffi = cffi.FFI()
        self._cpp_object = cpp.fem.create_form(ffi.cast("uintptr_t", ufc_form), function_spaces)

        # Need to fill the form with coefficients data
        # For every coefficient in form take its C++ object
        original_coefficients = form.coefficients()
        for i in range(self._cpp_object.num_coefficients()):
            j = self._cpp_object.original_coefficient_position(i)
            self._cpp_object.set_coefficient(
                i, original_coefficients[j]._cpp_object)

        # Constants are set based on their position in original form
        original_constants = [c._cpp_object for c in form.constants()]

        self._cpp_object.set_constants(original_constants)

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

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

        # Attach subdomains to C++ Form if we have them
        subdomains = self._subdomains.get("cell")
        if subdomains:
            self._cpp_object.set_cell_domains(subdomains)

        subdomains = self._subdomains.get("exterior_facet")
        if subdomains:
            self._cpp_object.set_exterior_facet_domains(subdomains)

        subdomains = self._subdomains.get("interior_facet")
        if subdomains:
            self._cpp_object.set_interior_facet_domains(subdomains)

        subdomains = self._subdomains.get("vertex")
        if subdomains:
            self._cpp_object.set_vertex_domains(subdomains)