Esempio n. 1
0
    def __init__(self, mesh, element, constrained_domain=None):
        """Create function space on given mesh for given finite element.

        *Arguments*
            mesh
                A :py:class:`Mesh <dolfin.cpp.Mesh>`
            element
                A :py:class:`(UFL) FiniteElement <ufl.FiniteElementBase>`

        """

        # Store reference to constrained domain to avoid possible SWIG
        # director memory error (see
        # https://bitbucket.org/fenics-project/dolfin/issue/71)
        self.constrained_domain = constrained_domain

        # Check arguments
        if not isinstance(mesh, (cpp.Mesh, cpp.Restriction)):
            cpp.dolfin_error(
                "functionspace.py", "create function space",
                "Illegal argument, not a mesh or restriction: " + str(mesh))
        if not isinstance(element, (ufl.FiniteElementBase)):
            cpp.dolfin_error(
                "functionspace.py", "create function space",
                "Illegal argument, not a finite element: " + str(element))
        if constrained_domain is not None:
            if not isinstance(constrained_domain, cpp.SubDomain):
                cpp.dolfin_error(
                    "functionspace.py", "create function space",
                    "Illegal argument, not a subdomain: " +
                    str(constrained_domain))

        # Store element Note: self._ufl_element cannot be a private
        # attribute as we want to be able to set the element from a
        # derived class.
        self._ufl_element = element

        # JIT-compile element to get ufc_element and ufc_dofmap
        ufc_element, ufc_dofmap = jit(self._ufl_element,
                                      mpi_comm=mesh.mpi_comm())

        # Instantiate DOLFIN FiniteElement and DofMap
        self._dolfin_element = cpp.FiniteElement(ufc_element)
        if constrained_domain is not None:
            if isinstance(mesh, cpp.Restriction):
                cpp.dolfin_error(
                    "functionspace.py", "create function space",
                    "Cannot use constrained domains together with restrictions."
                )
            dolfin_dofmap = cpp.DofMap(ufc_dofmap, mesh, constrained_domain)
        else:
            if isinstance(mesh, cpp.Restriction):
                dolfin_dofmap = cpp.DofMap(ufc_dofmap, mesh)
                mesh = mesh.mesh()
            else:
                dolfin_dofmap = cpp.DofMap(ufc_dofmap, mesh)

        # Initialize the cpp_FunctionSpace
        cpp.FunctionSpace.__init__(self, mesh, self._dolfin_element,
                                   dolfin_dofmap)
Esempio n. 2
0
    def __init__(self, mesh, element, constrained_domain=None):
        """Create function space on given mesh for given finite element.

        *Arguments*
            mesh
                A :py:class:`Mesh <dolfin.cpp.Mesh>`
            element
                A :py:class:`(UFL) FiniteElement <ufl.FiniteElementBase>`

        """

        # Store reference to constrained domain to avoid possible SWIG
        # director memory error (see
        # https://bitbucket.org/fenics-project/dolfin/issue/71)
        self.constrained_domain = constrained_domain

        # Check arguments
        if not isinstance(mesh, (cpp.Mesh, cpp.Restriction)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a mesh or restriction: " + str(mesh))
        if not isinstance(element, (ufl.FiniteElementBase)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a finite element: " + str(element))
        if constrained_domain is not None:
            if not isinstance(constrained_domain, cpp.SubDomain):
                cpp.dolfin_error("functionspace.py",
                                 "create function space",
                                 "Illegal argument, not a subdomain: " + str(constrained_domain))

        # Store element Note: self._ufl_element cannot be a private
        # attribute as we want to be able to set the element from a
        # derived class.
        self._ufl_element = element

        # JIT-compile element to get ufc_element and ufc_dofmap
        ufc_element, ufc_dofmap = jit(self._ufl_element, mpi_comm=mesh.mpi_comm())

        # Instantiate DOLFIN FiniteElement and DofMap
        self._dolfin_element = cpp.FiniteElement(ufc_element)
        if constrained_domain is not None:
            if isinstance(mesh, cpp.Restriction):
                cpp.dolfin_error("functionspace.py",
                                 "create function space",
                                 "Cannot use constrained domains together with restrictions.")
            dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh, constrained_domain)
        else:
            if isinstance(mesh, cpp.Restriction):
                dolfin_dofmap = cpp.DofMap(ufc_dofmap, mesh)
                mesh = mesh.mesh()
            else:
                dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh)

        # Initialize the cpp_FunctionSpace
        cpp.FunctionSpace.__init__(self, mesh,
                                   self._dolfin_element,
                                   dolfin_dofmap)
    def __init__(self, mesh, element, constrained_domain=None):
        """Create function space on given mesh for given finite element.

        *Arguments*
            mesh
                A :py:class:`Mesh <dolfin.cpp.Mesh>`
            element
                A :py:class:`(UFL) FiniteElement <ufl.FiniteElementBase>`

        """

        # Check arguments
        if not isinstance(mesh, (cpp.Mesh, cpp.Restriction)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a mesh or restriction: " + str(mesh))
        if not isinstance(element, (ufl.FiniteElementBase)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a finite element: " + str(element))
        if constrained_domain is not None:
            if not isinstance(constrained_domain, cpp.SubDomain):
                cpp.dolfin_error("functionspace.py",
                                 "create function space",
                                 "Illegal argument, not a subdomain: " + str(constrained_domain))

        # Store element
        # Note: self._ufl_element cannot be a private attribute as we want to be able to
        #       set the element from a derived class.
        self._ufl_element = element

        # JIT-compile element to get ufc_element and ufc_dofmap
        ufc_element, ufc_dofmap = jit(self._ufl_element)

        # Instantiate DOLFIN FiniteElement and DofMap
        self._dolfin_element = cpp.FiniteElement(ufc_element)
        if constrained_domain is not None:
            if isinstance(mesh, cpp.Restriction):
                cpp.dolfin_error("functionspace.py",
                                 "create function space",
                                 "Cannot use constrained domains together with restrictions.")
            dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh, constrained_domain)
        else:
            if isinstance(mesh, cpp.Restriction):
                dolfin_dofmap = cpp.DofMap(ufc_dofmap, mesh)
                mesh = mesh.mesh()
            else:
                dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh)

        # Initialize the cpp_FunctionSpace
        cpp.FunctionSpace.__init__(self, mesh,
                                   self._dolfin_element,
                                   dolfin_dofmap)
Esempio n. 4
0
    def __init__(self, mesh, element, constrained_domain=None):
        """Create function space on given mesh for given finite element.

        *Arguments*
            mesh
                A :py:class:`Mesh <dolfin.cpp.Mesh>`
            element
                A :py:class:`(UFL) FiniteElement <ufl.FiniteElementBase>`

        """

        # Check arguments
        if not isinstance(mesh, (cpp.Mesh, cpp.Restriction)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a mesh or restriction: " + str(mesh))
        if not isinstance(element, (ufl.FiniteElementBase)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a finite element: " + str(element))
        if constrained_domain is not None:
            if not isinstance(constrained_domain, cpp.SubDomain):
                cpp.dolfin_error("functionspace.py",
                                 "create function space",
                                 "Illegal argument, not a subdomain: " + str(constrained_domain))

        # Store element
        # Note: self._element cannot be a private attribute as we want to be able to
        #       set the element from a derived class.
        self._ufl_element = element

        # JIT-compile element to get ufc_element and ufc_dofmap
        ufc_element, ufc_dofmap = jit(self._ufl_element)

        # Instantiate DOLFIN FiniteElement and DofMap
        self._dolfin_element = cpp.FiniteElement(ufc_element)
        if constrained_domain is not None:
            if isinstance(mesh, cpp.Restriction):
                cpp.dolfin_error("functionspace.py",
                                 "create function space",
                                 "Cannot use constrained domains together with restrictions.")
            dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh, constrained_domain)
        else:
            if isinstance(mesh, cpp.Restriction):
                dolfin_dofmap = cpp.DofMap(ufc_dofmap, mesh)
                mesh = mesh.mesh()
            else:
                dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh)

        # Initialize the cpp_FunctionSpace
        cpp.FunctionSpace.__init__(self, mesh,
                                   self._dolfin_element,
                                   dolfin_dofmap)
Esempio n. 5
0
    def __init__(self, form,
                 function_spaces=None,
                 coefficients=None,
                 subdomains=None,
                 form_compiler_parameters=None,
                 common_cell=None):
        "Create JIT-compiled form from any given form (compiled or not)."

        # Check form argument
        if isinstance(form, ufl.Form):
            self._compiled_form, module, self.form_data, prefix \
                                 = jit(form, form_compiler_parameters,
                                       common_cell)

        elif isinstance(form, ufc.form):
            self._compiled_form = form
            self.form_data = None

        elif isinstance(form, cpp.Form):
            self._compiled_form = form._compiled_form
            self.form_data = form.form_data

        else:
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "Expected a ufl.Form, ufc.form or a dolfin.Form")

        # Extract function spaces
        self.function_spaces = _extract_function_spaces(self.form_data,
                                                        self._compiled_form,
                                                        function_spaces)

        # Extract coefficients
        (self.coefficients, self._compiled_coefficients) = \
            _extract_coefficients(self.form_data, coefficients)

        # Initialize base class
        cpp.Form.__init__(self, self._compiled_form,
                          self.function_spaces, self.coefficients)

        # Extract subdomains from form_data, override if given explicitly
        self.subdomains = _extract_subdomains(self.form_data, subdomains)

        # Attach subdomains 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)
Esempio n. 6
0
def _compile_dolfin_element(element, mesh, constrained_domain=None):
    "Instantiate DOLFIN FiniteElement and DofMap from ufl element."

    # JIT-compile element to get ufc_element and ufc_dofmap
    ufc_element, ufc_dofmap = jit(element, mpi_comm=mesh.mpi_comm())

    dolfin_element = cpp.FiniteElement(ufc_element)

    if constrained_domain is None:
        dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh)
    else:
        dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh, constrained_domain)

    return dolfin_element, dolfin_dofmap
Esempio n. 7
0
def _compile_dolfin_element(element, mesh, constrained_domain=None):
    "Instantiate DOLFIN FiniteElement and DofMap from ufl element."

    # JIT-compile element to get ufc_element and ufc_dofmap
    ufc_element, ufc_dofmap = jit(element, mpi_comm=mesh.mpi_comm())

    dolfin_element = cpp.FiniteElement(ufc_element)

    if constrained_domain is None:
        dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh)
    else:
        dolfin_dofmap  = cpp.DofMap(ufc_dofmap, mesh, constrained_domain)

    return dolfin_element, dolfin_dofmap
Esempio n. 8
0
    def __init__(self,
                 form,
                 form_compiler_parameters=None,
                 function_spaces=None):
        "Create JIT-compiled form from any given form (compiled or not)."

        # Developer note: The function_spaces argument is used to
        # handle forms defined on multimesh function spaces. These are
        # really defined over a standard function space (the first of
        # the spaces) then later recreated on each function space part
        # and added together to form a multimesh form. This happens in
        # the function assemble_multimesh.

        # Check form argument
        if not isinstance(form, ufl.Form):
            cpp.dolfin_error("form.py", "creating dolfin.Form",
                             "Expected a ufl.Form.")

        # Cutoff for better error message than ffc would give
        if not form.empty() and not form.ufl_domains():
            cpp.dolfin_error(
                "form.py", "creating dolfin.Form",
                "The ufl.Form does not include any reference to a mesh.")

        # Extract subdomain data.
        # Until the assembler and ufc has multimesh support,
        # we impose the limitation of a single domain at this point.
        sd = form.subdomain_data()
        if len(sd) != 1:
            cpp.dolfin_error(
                "form.py", "creating dolfin.Form",
                "Expecting subdomain data for a single domain only.")
        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 now a strict requirement
        if mesh is None:
            cpp.dolfin_error("form.py", "creating dolfin.Form",
                             "Expecting to find a Mesh in the form.")

        # Jit the module, this will take some time...
        jit_result = jit(form,
                         form_compiler_parameters,
                         mpi_comm=mesh.mpi_comm())
        if jit_result is None:
            cpp.dolfin_error("form.py", "creating dolfin.Form", "jit failure.")
        self._compiled_form, module, prefix = jit_result

        # Extract function spaces of form arguments
        if function_spaces is None:
            self.function_spaces = [
                func.function_space() for func in form.arguments()
            ]
        else:
            self.function_spaces = function_spaces

        # Type checking argument function_spaces
        if not all(
                isinstance(fs, cpp.FunctionSpace)
                for fs in self.function_spaces):
            raise ValueError(function_space_error +
                             " Invalid type of test spaces.")

        # Initialize base class
        cpp.Form.__init__(self, self._compiled_form, self.function_spaces)

        # Type checking argument function_spaces
        #r = self._compiled_form.rank()
        #if len(self.function_spaces) != r:
        #    raise ValueError(function_space_error +
        #                     " Wrong number of test spaces (should be %d)." % r)

        # Extract coefficients from form (pass only the ones that
        # the compiled form actually uses to the assembler)
        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])

        # Type checking coefficients
        if not all(
                isinstance(c, (cpp.GenericFunction, cpp.MultiMeshFunction))
                for c in self.coefficients):
            # Developer note:
            # The form accepts a MultiMeshFunction but does not set the
            # correct coefficients. This is done in assemble_multimesh
            # at the moment
            coefficient_error = "Error while extracting coefficients. "
            raise TypeError(coefficient_error +
                            "Either provide a dict of cpp.GenericFunctions, " +
                            "or use Function to define your form.")

        for i in range(self.num_coefficients()):
            if isinstance(self.coefficients[i], cpp.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)
        # Type checking subdomain data
        # Delete None entries
        for k in list(self.subdomains.keys()):
            if self.subdomains[k] is None:
                del self.subdomains[k]
        # Check that we have no additional subdomain data (user
        # misspelling)
        # TODO: Get from ufl list?
        integral_types = ("cell", "exterior_facet", "interior_facet", "vertex")
        additional_keys = set(self.subdomains.keys()) - set(integral_types)
        if additional_keys:
            cpp.warning("Invalid keys in subdomains: %s" % additional_keys)
        # Check that we have only MeshFunctions
        for data in list(self.subdomains.values()):
            if not (data is None or isinstance(data, MeshFunctionSizet)):
                cpp.warning(
                    "Invalid subdomain data type %s, expecting a MeshFunction"
                    % type(data))

        # 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 __init__(self, form,
                 function_spaces=None,
                 coefficients=None,
                 subdomains=None,
                 form_compiler_parameters=None,
                 common_cell=None, # deprecated
                 mesh=None):
        "Create JIT-compiled form from any given form (compiled or not)."

        # Check form argument
        if isinstance(form, ufl.Form):
            # Complete form with domain before sending to jit
            common_domain = get_common_domain(mesh, common_cell)
            if common_domain is not None:
                form = replace_integral_domains(form, common_domain)
                
            if not form.empty():
                assert form.domains(), "Expecting a completed form with domains at this point."

            self._compiled_form, module, self.form_data, prefix \
                                 = jit(form, form_compiler_parameters)
            # If we got no mesh, try to get mesh from domain data,
            # to handle e.g. assemble(1*dx(mesh))
            if mesh is None:
                fd = form.form_data()
                domains = fd.preprocessed_form.domains()
                if len(domains) == 1:
                    # Note: mesh here could still be None, depends on what the user did
                    mesh = domains[0].data()

        elif isinstance(form, ufc.form):
            self._compiled_form = form
            self.form_data = None

        elif isinstance(form, cpp.Form):
            self._compiled_form = form._compiled_form
            self.form_data = form.form_data

        else:
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "Expected a ufl.Form, ufc.form or a dolfin.Form")

        # Extract function spaces
        self.function_spaces = _extract_function_spaces(self.form_data,
                                                        self._compiled_form,
                                                        function_spaces)

        # Extract coefficients
        (self.coefficients, self._compiled_coefficients) = \
            _extract_coefficients(self.form_data, coefficients)

        # Initialize base class
        cpp.Form.__init__(self, self._compiled_form,
                          self.function_spaces, self.coefficients)

        # Extract subdomains from form_data, override if given explicitly
        self.subdomains = _extract_subdomains(self.form_data, subdomains)

        # Attach subdomains 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)

        # Set mesh if specified (important for functionals without a function spaces)
        if mesh is not None:
            self.set_mesh(mesh)
Esempio n. 10
0
    def __init__(self, form, form_compiler_parameters=None):
        "Create JIT-compiled form from any given form (compiled or not)."

        # Check form argument
        if not isinstance(form, ufl.Form):
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "Expected a ufl.Form.")

        # Cutoff for better error message than ffc would give
        if not form.empty() and not form.domains():
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "The ufl.Form does not include any reference to a mesh.")

        # Extract subdomain data.
        # Until the assembler and ufc has multimesh support,
        # we impose the limitation of a single domain at this point.
        sd = form.subdomain_data()
        if len(sd) != 1:
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "Expecting subdomain data for a single domain only.")
        self.subdomains, = list(sd.values()) # Assuming single domain
        domain, = list(sd.keys()) # Assuming single domain
        mesh = domain.data()

        # Having a mesh in the form is now a strict requirement
        if mesh is None:
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "Expecting to find a Mesh in the form.")

        # Jit the module, this will take some time...
        self._compiled_form, module, prefix \
                             = jit(form, form_compiler_parameters,
                                   mpi_comm=mesh.mpi_comm())

        # Extract function spaces of form arguments
        self.function_spaces = [func.function_space() for func in form.arguments()]

        # Extract coefficients from form (pass only the ones that
        # the compiled form actually uses to the assembler)
        original_coefficients = form.coefficients()
        self.coefficients = []
        for i in range(self._compiled_form.num_coefficients()):
            j = self._compiled_form.original_coefficient_position(i)
            self.coefficients.append(original_coefficients[j])

        # Type checking argument function_spaces
        r = self._compiled_form.rank()
        if len(self.function_spaces) != r:
            raise ValueError(function_space_error +
                  " Wrong number of test spaces (should be %d)." % r)
        if not all(isinstance(fs, cpp.FunctionSpace) for fs in self.function_spaces):
            raise ValueError(function_space_error +
                  " Invalid type of test spaces.")

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

        # Initialize base class
        cpp.Form.__init__(self, self._compiled_form,
                          self.function_spaces, self.coefficients)

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


        # Type checking subdomain data
        # Delete None entries
        for k in list(self.subdomains.keys()):
            if self.subdomains[k] is None:
                del self.subdomains[k]
        # Check that we have no additional subdomain data (user misspelling)
        # TODO: Get from ufl list?
        integral_types = ("cell", "exterior_facet", "interior_facet", "vertex")
        additional_keys = set(self.subdomains.keys()) - set(integral_types)
        if additional_keys:
            cpp.warning("Invalid keys in subdomains: %s" % additional_keys)
        # Check that we have only MeshFunctions
        for data in list(self.subdomains.values()):
            if not (data is None or isinstance(data, MeshFunctionSizet)):
                cpp.warning("Invalid subdomain data type %s, expecting a MeshFunction" % type(data))

        # 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. 11
0
    def __init__(
            self,
            form,
            function_spaces=None,
            coefficients=None,
            subdomains=None,
            form_compiler_parameters=None,
            common_cell=None,  # deprecated
            mesh=None):
        "Create JIT-compiled form from any given form (compiled or not)."

        # Check form argument
        if isinstance(form, ufl.Form):
            # Complete form with domain before sending to jit
            common_domain = get_common_domain(mesh, common_cell)
            if common_domain is not None:
                form = replace_integral_domains(form, common_domain)

            if not form.empty():
                assert form.domains(
                ), "Expecting a completed form with domains at this point."

            self._compiled_form, module, self.form_data, prefix \
                                 = jit(form, form_compiler_parameters)
            # If we got no mesh, try to get mesh from domain data,
            # to handle e.g. assemble(1*dx(mesh))
            if mesh is None:
                fd = form.form_data()
                domains = fd.preprocessed_form.domains()
                if len(domains) == 1:
                    # Note: mesh here could still be None, depends on what the user did
                    mesh = domains[0].data()

        elif isinstance(form, ufc.form):
            self._compiled_form = form
            self.form_data = None

        elif isinstance(form, cpp.Form):
            self._compiled_form = form._compiled_form
            self.form_data = form.form_data

        else:
            cpp.dolfin_error("form.py", "creating dolfin.Form",
                             "Expected a ufl.Form, ufc.form or a dolfin.Form")

        # Extract function spaces
        self.function_spaces = _extract_function_spaces(
            self.form_data, self._compiled_form, function_spaces)

        # Extract coefficients
        (self.coefficients, self._compiled_coefficients) = \
            _extract_coefficients(self.form_data, coefficients)

        # Initialize base class
        cpp.Form.__init__(self, self._compiled_form, self.function_spaces,
                          self.coefficients)

        # Extract subdomains from form_data, override if given explicitly
        self.subdomains = _extract_subdomains(self.form_data, subdomains)

        # Attach subdomains 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)

        # Set mesh if specified (important for functionals without a function spaces)
        if mesh is not None:
            self.set_mesh(mesh)
Esempio n. 12
0
    def __init__(self, form,
                 form_compiler_parameters=None,
                 subdomains=None):
        "Create JIT-compiled form from any given form (compiled or not)."

        # Check form argument
        if isinstance(form, ufl.Form):
            # Cutoff for better error message than ffc would give
            if not form.empty() and not form.domains():
                raise RuntimeError("Expecting a completed form with domains at this point.")

            # Extract subdomain data
            sd = form.subdomain_data()
            if len(sd) != 1:
                # Until the assembler and ufc has multimesh support, we impose this limitation
                raise RuntimeError("Expecting subdomain data for a single domain only.")
            if subdomains is None:
                self.subdomains, = list(sd.values()) # Assuming single domain
            domain, = list(sd.keys()) # Assuming single domain
            mesh = domain.data()

            # Jit the module, this will take some time...
            self._compiled_form, module, prefix \
                                 = jit(form, form_compiler_parameters,
                                       mpi_comm=mesh.mpi_comm())

            # Extract function spaces of form arguments
            self.function_spaces = [func.function_space() for func in form.arguments()]

            # Extract coefficients from form (pass only the ones that the compiled form actually uses to the assembler)
            original_coefficients = form.coefficients()
            self.coefficients = [original_coefficients[self._compiled_form.original_coefficient_position(i)]
                                 for i in range(self._compiled_form.num_coefficients())]

        elif isinstance(form, cpp.Form):
            cpp.deprecation("Passing a cpp.Form to dolfin.Form constructor",
                            "1.3.0", "1.4.0",
                            "Passing a cpp.Form to dolfin.Form constructor"
                            " will be removed.")
            self._compiled_form = form._compiled_form

            self.function_spaces = form.function_spaces
            self.coefficients = form.coefficients
            self.subdomains = form.subdomains
            mesh = form.mesh()

        else:
            cpp.dolfin_error("form.py",
                             "creating dolfin.Form",
                             "Expected a ufl.Form or a dolfin.Form")

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

        # Type checking argument function_spaces
        r = self._compiled_form.rank()
        if len(self.function_spaces) != r:
            raise ValueError(function_space_error +
                  " Wrong number of test spaces (should be %d)." % r)
        if not all(isinstance(fs, cpp.FunctionSpace) for fs in self.function_spaces):
            raise ValueError(function_space_error +
                  " Invalid type of test spaces.")

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

        # Type checking subdomain data
        # Check that we have no additional subdomain data (user misspelling)
        # TODO: Get from ufl list?
        integral_types = ("cell", "exterior_facet", "interior_facet", "point") 
        for k in list(self.subdomains.keys()):
            if self.subdomains[k] is None:
                del self.subdomains[k]
        additional_keys = set(self.subdomains.keys()) - set(integral_types)
        if additional_keys:
            cpp.warning("Invalid keys in subdomains: %s" % additional_keys)
        # Check that we have only MeshFunctions
        for data in list(self.subdomains.values()):
            # TODO: This wasn't here before, disable if it's too restrictive:
            if not (data is None or isinstance(data, MeshFunctionSizet)):
                cpp.warning("Invalid subdomain data type %s, expecting a MeshFunction" % type(data))

        # Initialize base class
        cpp.Form.__init__(self, self._compiled_form,
                          self.function_spaces, self.coefficients)

        # Attach subdomains 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("point")

        if subdomains is not None:
            self.set_vertex_domains(subdomains)

        # Attach mesh
        self.set_mesh(mesh)