Exemple #1
0
    def _init_from_ufl(self, mesh, element, constrained_domain=None):
        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))

        # Compile element and dofmap and construct corresponding dolfin objects
        #if dolfin_element is None or dolfin_dofmap is None:
        #    assert dolfin_element is None and dolfin_dofmap is None, "Expecting both or none of these."
        dolfin_element, dolfin_dofmap = _compile_dolfin_element(element, mesh, constrained_domain=constrained_domain)

        # Initialize the cpp.FunctionSpace
        cpp.FunctionSpace.__init__(self, mesh, dolfin_element, dolfin_dofmap)

        # Initialize the ufl.FunctionSpace
        ufl.FunctionSpace.__init__(self, mesh.ufl_domain(), element)

        # Store reference to constrained domain to avoid possible SWIG
        # director memory error (see
        # https://bitbucket.org/fenics-project/dolfin/issue/71)
        # TODO: Make constrained_domain private with getter? Attribute access breaks interface consistency.
        self.constrained_domain = constrained_domain
Exemple #2
0
def jit(form, form_compiler_parameters=None):
    """Just-in-time compile any provided form.

    It uses the jit function from the form compiler registered by
    parameters["form_compiler"]["name"].
    """

    # Check that form is not empty
    if isinstance(form, ufl.Form):
        if form.empty():
            raise RuntimeError, "Form is empty. Cannot pass to JIT compiler."

    # Import form compiler
    form_compiler_name = cpp.parameters["form_compiler"]["name"]
    try:
        form_compiler = __import__(form_compiler_name)
    except ImportError, message:
        print message
        warning("Could not import %s form compiler, falling back to FFC." \
                % form_compiler_name)
        try:
            form_compiler = __import__("ffc")
        except:
            cpp.dolfin_error("jit.py",
                             "perform just-in-time compilation of form",
                             "Could not import FFC form compiler")
Exemple #3
0
def interpolate(v, V):
    """
    Return interpolation of a given function into a given finite element space.

    *Arguments*
        v
            a :py:class:`Function <dolfin.functions.function.Function>` or
            an :py:class:`Expression <dolfin.functions.expression.Expression>`
        V
            a :py:class:`FunctionSpace (standard, mixed, etc.)
            <dolfin.functions.functionspace.FunctionSpaceBase>`

    *Example of usage*

        .. code-block:: python

            v = Expression("sin(pi*x[0])")
            V = FunctionSpace(mesh, "Lagrange", 1)
            Iv = interpolate(v, V)

    """

    # Check arguments
    if not isinstance(V, FunctionSpaceBase):
        cpp.dolfin_error(
            "interpolation.py", "compute interpolation",
            "Illegal function space for interpolation, not a FunctionSpace (%s)"
            % str(v))

    # Compute interpolation
    Pv = Function(V)
    Pv.interpolate(v)

    return Pv
Exemple #4
0
def MultiMeshFunctionSpace(multimesh, family, degree=None):
    """Create multimesh finite element function space.

    *Arguments*
        multimesh
            a :py:class:`MultiMesh <dolfin.cpp.MultiMesh>`.
        family
            a string specifying the element family,
            see :py:class:`FunctionSpace
            <dolfin.functions.functionspace.FunctionSpace>`
            for alternatives.

            This argument may also be a `FiniteElement`, in
            which case the `degree` argument should not be
            specified.
        degree
            the degree of the element.

    *Example of usage*

        .. code-block:: python

            V = MultiMeshFunctionSpace(mesh, "CG", 1)

            element = FiniteElement("Lagrange", triangle, 1)
            V = MultiMeshFunctionSpace(mesh, element)

    Note: Multimesh function spaces does currently not support
    function space algebra. For this reason, mixed function spaces
    and the like must be created via a finite element.
    """

    # Check arguments
    if not isinstance(multimesh, cpp.MultiMesh):
        cpp.dolfin_error("functionspace.py",
                         "create multimesh function space",
                         "Illegal argument, not a multimesh: " + str(multimesh))

    # Create element if not supplied
    if isinstance(family, ufl.FiniteElementBase):
        element = family
    else:
        mesh = multimesh.part(0)
        element = ufl.FiniteElement(family, mesh.ufl_cell(), degree)

    # Create and add individual function spaces
    V = cpp.MultiMeshFunctionSpace(multimesh)
    V_parts = []
    for part in range(multimesh.num_parts()):
        V_part = FunctionSpace(multimesh.part(part), element)
        V_parts.append(V_part)
        V.add(V_part)

    # Build multimesh function space
    V.build()

    # Store full function spaces
    V._parts = V_parts

    return V
Exemple #5
0
def EnrichedFunctionSpace(spaces):
    """
    Create enriched finite element function space.

    *Arguments*
        spaces
            a list (or tuple) of :py:class:`FunctionSpaces
            <dolfin.functions.functionspace.FunctionSpace>`.

    *Usage*
        The function space may be created by

        .. code-block:: python

            V = EnrichedFunctionSpace(spaces)

    """
    cpp.deprecation("'EnrichedFunctionSpace'", "1.7.0", "2.0.0",
                    "Use 'FunctionSpace(mesh, EnrichedElement(...))'.")

    # Check arguments
    if not len(spaces) > 0:
        cpp.dolfin_error("functionspace.py", "create enriched function space",
                         "Need at least one subspace")
    if not all(isinstance(V, FunctionSpace) for V in spaces):
        cpp.dolfin_error("functionspace.py", "create enriched function space",
                         "Invalid subspaces: " + str(spaces))

    # Get common mesh and constrained_domain, must all be the same
    mesh, constrained_domain = _get_common_mesh_and_constrained_domain(spaces)

    # Create element
    element = ufl.EnrichedElement(*[V.ufl_element() for V in spaces])

    return FunctionSpace(mesh, element, constrained_domain=constrained_domain)
Exemple #6
0
    def _init_convenience(self,
                          mesh,
                          family,
                          degree,
                          form_degree=None,
                          constrained_domain=None,
                          restriction=None):
        # Check arguments
        if not isinstance(family, string_types):
            cpp.dolfin_error(
                "functionspace.py", "create function space",
                "Illegal argument for finite element family, not a string: " +
                str(family))
        if not isinstance(degree, int):
            cpp.dolfin_error(
                "functionspace.py", "create function space",
                "Illegal argument for degree, not an integer: " + str(degree))

        # Create UFL element
        element = ufl.FiniteElement(family,
                                    mesh.ufl_cell(),
                                    degree,
                                    form_degree=form_degree)
        if restriction is not None:
            element = element[restriction]

        self._init_from_ufl(mesh,
                            element,
                            constrained_domain=constrained_domain)
Exemple #7
0
def jit(form, form_compiler_parameters=None, common_cell=None):
    """Just-in-time compile any provided form.

    It uses the jit function from the form compiler registered by
    parameters["form_compiler"]["name"].
    """

    # Check that form is not empty
    if isinstance(form, ufl.Form):
        if form.integrals() == ():
            raise RuntimeError, "Form is empty. Cannot pass to JIT compiler."

    # Import form compiler
    form_compiler_name = cpp.parameters["form_compiler"]["name"]
    try:
        form_compiler = __import__(form_compiler_name)
    except ImportError, message:
        print message
        warning("Could not import %s form compiler, falling back to FFC." % form_compiler_name)
        try:
            form_compiler = __import__("ffc")
        except:
            cpp.dolfin_error("jit.py",
                             "perform just-in-time compilation of form",
                             "Could not import FFC form compiler")
Exemple #8
0
    def _init_from_ufl(self, mesh, element, constrained_domain=None):
        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))

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

        # Compile element and dofmap and construct corresponding dolfin objects
        dolfin_element, dolfin_dofmap = _compile_dolfin_element(element, mesh, constrained_domain=constrained_domain)

        # Initialize the cpp.FunctionSpace
        cpp.FunctionSpace.__init__(self, mesh, dolfin_element, dolfin_dofmap)

        # Store reference to constrained domain to avoid possible SWIG
        # director memory error (see
        # https://bitbucket.org/fenics-project/dolfin/issue/71)
        # TODO: Make constrained_domain private with getter? Attribute access breaks interface consistency.
        self.constrained_domain = constrained_domain
def derivative(form, u, du=None, coefficient_derivatives=None):
    if du is None:
        # Get existing arguments from form and position the new one with the next argument number
        from ufl.algorithms import extract_arguments
        form_arguments = extract_arguments(form)

        number = max([-1] + [arg.number() for arg in form_arguments]) + 1

        if any(arg.part() is not None for arg in form_arguments):
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create third argument using parts, please supply one")
        part = None

        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V, number, part)
        elif isinstance(u, (list,tuple)) and all(isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V, number, part))
        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create third argument, please supply one")
    return ufl.derivative(form, u, du, coefficient_derivatives)
Exemple #10
0
def EnrichedFunctionSpace(spaces):
    """
    Create enriched finite element function space.

    *Arguments*
        spaces
            a list (or tuple) of :py:class:`FunctionSpaces
            <dolfin.functions.functionspace.FunctionSpace>`.

    *Usage*
        The function space may be created by

        .. code-block:: python

            V = EnrichedFunctionSpace(spaces)

    """
    cpp.deprecation("'EnrichedFunctionSpace'", "1.7.0", "2.0.0", "Use 'FunctionSpace(mesh, EnrichedElement(...))'.")

    # Check arguments
    if not len(spaces) > 0:
        cpp.dolfin_error("functionspace.py", "create enriched function space", "Need at least one subspace")
    if not all(isinstance(V, FunctionSpace) for V in spaces):
        cpp.dolfin_error("functionspace.py", "create enriched function space", "Invalid subspaces: " + str(spaces))

    # Get common mesh and constrained_domain, must all be the same
    mesh, constrained_domain = _get_common_mesh_and_constrained_domain(spaces)

    # Create element
    element = ufl.EnrichedElement(*[V.ufl_element() for V in spaces])

    return FunctionSpace(mesh, element, constrained_domain=constrained_domain)
    def extract_sub_space(self, component):
        """
        Extract subspace for component

        *Arguments*
            component (numpy.array(uint))
               The component.

        *Returns*
            _FunctionSpace_
                The subspace.
        """

        # Transform the argument to a NumPy array
        if not hasattr(component, "__len__"):
            cpp.dolfin_error("functionspace.py",
                             "extracting sub spaces",
                             "Expected a component which is iterable")
        component = numpy.asarray(component, dtype=numpy.uintp)

        # Get the cpp version of the FunctionSpace
        cpp_space = cpp.FunctionSpace.extract_sub_space(self, component)

        # Instantiate a ufl finite element based on the dolfin element signature
        element = eval(cpp_space.element().signature(), ufl.__dict__).reconstruct(domain=self.mesh())
        return FunctionSpaceFromCpp(cpp_space, element)
Exemple #12
0
def _extract_u(u):
    "Extract and check argument u"
    if not isinstance(u, cpp.Function):
        cpp.dolfin_error("solving.py",
                         "solve variational problem",
                         "Expecting second argument to be a Function")
    return u
Exemple #13
0
def _extract_eq(eq):
    "Extract and check argument eq"
    if not isinstance(eq, ufl.classes.Equation):
        cpp.dolfin_error("solving.py",
                         "solve variational problem",
                         "Expecting first argument to be an Equation")
    return eq
Exemple #14
0
def compute_edge_map(mesh0, mesh1):
    """
    Compute map from edges of mesh0 to vertices of mesh1.

    *Arguments*
        mesh0
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.
        mesh1
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.

    It is assumed that both meshes have a :py:class:`MeshFunction
    <dolfin.cpp.MeshFunction>` over the vertices named
    "parent_vertex_indices" which contain a mapping from the
    local vertices to a common parent vertex numbering.

    """

    # Check arguments
    if not isinstance(mesh0, Mesh):
        raise TypeError, "expected 'Mesh' as argument"
    if not isinstance(mesh1, Mesh):
        raise TypeError, "expected 'Mesh' as argument"

    # Get parent vertex numbers
    vertices0 = mesh0.data().array("parent_vertex_indices", 0)
    vertices1 = mesh1.data().array("parent_vertex_indices", 0)

    # Check mappings
    if len(vertices0) == 0  or len(vertices1) == 0:
        cpp.dolfin_error("ale.py",
                         "compute edge map",
                         "Parent vertex indices are missing")

    # Initialize edges
    mesh0.init(1)
    mesh1.init(1)

    # Build parent to local map from vertex pair to local edge for mesh0
    parent_to_local_mesh0 = {}
    for edge in edges(mesh0):
        v = [vertices0[int(i)] for i in edge.entities(0)]
        v.sort()
        parent_to_local_mesh0[tuple(v)] = edge.index()

    # Build parent to local map from vertex pair to local edge for mesh1
    parent_to_local_mesh1 = {}
    for edge in edges(mesh1):
        v = [vertices1[int(i)] for i in edge.entities(0)]
        v.sort()
        parent_to_local_mesh1[tuple(v)] = edge.index()

    # Get common edges
    common_edges = set(parent_to_local_mesh0.iterkeys()).intersection(set(parent_to_local_mesh1.iterkeys()))

    # Compute map
    edge_map = {}
    for edge in common_edges:
        edge_map[parent_to_local_mesh0[edge]] = parent_to_local_mesh1[edge]

    return edge_map
Exemple #15
0
def compute_edge_map(mesh0, mesh1):
    """
    Compute map from edges of mesh0 to vertices of mesh1.

    *Arguments*
        mesh0
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.
        mesh1
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.

    It is assumed that both meshes have a :py:class:`MeshFunction
    <dolfin.cpp.MeshFunction>` over the vertices named
    "parent_vertex_indices" which contain a mapping from the
    local vertices to a common parent vertex numbering.

    """

    # Check arguments
    if not isinstance(mesh0, cpp.mesh.Mesh) or not isinstance(
            mesh1, cpp.mesh.Mesh):
        cpp.dolfin_error("ale.py", "compute edge map",
                         "Expected 'Mesh' as argument")

    # Get parent vertex numbers
    vertices0 = mesh0.data().array("parent_vertex_indices", 0)
    vertices1 = mesh1.data().array("parent_vertex_indices", 0)

    # Check mappings
    if len(vertices0) == 0 or len(vertices1) == 0:
        cpp.dolfin_error("ale.py", "compute edge map",
                         "Parent vertex indices are missing")

    # Initialize edges
    mesh0.init(1)
    mesh1.init(1)

    # Build parent to local map from vertex pair to local edge for mesh0
    parent_to_local_mesh0 = {}
    for edge in edges(mesh0):
        v = [vertices0[int(i)] for i in edge.entities(0)]
        v.sort()
        parent_to_local_mesh0[tuple(v)] = edge.index()

    # Build parent to local map from vertex pair to local edge for mesh1
    parent_to_local_mesh1 = {}
    for edge in edges(mesh1):
        v = [vertices1[int(i)] for i in edge.entities(0)]
        v.sort()
        parent_to_local_mesh1[tuple(v)] = edge.index()

    # Get common edges
    common_edges = set(parent_to_local_mesh0.keys()).intersection(
        set(parent_to_local_mesh1.keys()))

    # Compute map
    edge_map = {}
    for edge in common_edges:
        edge_map[parent_to_local_mesh0[edge]] = parent_to_local_mesh1[edge]

    return edge_map
Exemple #16
0
    def __init__(self, *args, **kwargs):
        "Create Dirichlet boundary condition"

        # Copy constructor
        if len(args) == 1:
            if not isinstance(args[0], cpp.DirichletBC):
                cpp.dolfin_error("bcs.py",
                                 "create DirichletBC",
                                 "Expecting a DirichleBC as only argument"\
                                 " for copy constructor")

            # Initialize base class
            cpp.DirichletBC.__init__(self, args[0])
            return

        # Special case for value specified as float, tuple or similar
        if len(args) >= 2 and not isinstance(args[1], cpp.GenericFunction):
            if isinstance(args[1], ufl.classes.Expr):
                expr = project(args[1], args[0])
            else:
                expr = Constant(args[1]) # let Constant handle all problems
            args = args[:1] + (expr,) + args[2:]

        # Special case for sub domain specified as a function
        if len(args) >= 3 and isinstance(args[2], types.FunctionType):
            sub_domain = AutoSubDomain(args[2])
            args = args[:2] + (sub_domain,) + args[3:]

        # Special case for sub domain specified as a string
        if len(args) >= 3 and isinstance(args[2], str):
            sub_domain = compile_subdomains(args[2])
            args = args[:2] + (sub_domain,) + args[3:]

        # Store Expression to avoid scoping issue with SWIG directors
        if isinstance(args[1], cpp.Expression):
            self.function_arg = args[1]

        # Store SubDomain to avoid scoping issue with SWIG directors
        self.domain_args = args[2:]

        # FIXME: Handling of multiple default arguments does not
        # really work between Python and C++ when C++ requires them to
        # be ordered and cannot accept the latter without the
        # former...

        # Add keyword arguments (in correct order...)
        allowed_kwargs = ["method", "check_midpoint"]
        for key in allowed_kwargs:
            if key in kwargs:
                args = tuple(list(args) + [kwargs[key]])

        # Check for other keyword arguments
        for key in kwargs:
            if not key in allowed_kwargs:
                cpp.dolfin_error("bcs.py",
                                 "create boundary condition",
                                 "Unknown keyword argument \"%s\"" % key)

        # Initialize base class
        cpp.DirichletBC.__init__(self, *args)
Exemple #17
0
def interpolate(v, V):
    """
    Return interpolation of a given function into a given finite element space.

    *Arguments*
        v
            a :py:class:`Function <dolfin.functions.function.Function>` or
            an :py:class:`Expression <dolfin.functions.expression.Expression>`
        V
            a :py:class:`FunctionSpace (standard, mixed, etc.)
            <dolfin.functions.functionspace.FunctionSpace>`

    *Example of usage*

        .. code-block:: python

            v = Expression("sin(pi*x[0])")
            V = FunctionSpace(mesh, "Lagrange", 1)
            Iv = interpolate(v, V)

    """

    # Check arguments
    if not isinstance(V, FunctionSpace):
        cpp.dolfin_error("interpolation.py",
                         "compute interpolation",
                         "Illegal function space for interpolation, not a FunctionSpace (%s)" % str(v))

    # Compute interpolation
    Pv = Function(V)
    Pv.interpolate(v)

    return Pv
Exemple #18
0
def _extract_eq(eq):
    "Extract and check argument eq"
    if not isinstance(eq, ufl.classes.Equation):
        cpp.dolfin_error("solving.py",
                         "solve variational problem",
                         "Expecting first argument to be an Equation")
    return eq
Exemple #19
0
    def __init__(self, *args, **kwargs):
        "Create Dirichlet boundary condition"

        # Copy constructor
        if len(args) == 1:
            if not isinstance(args[0], cpp.DirichletBC):
                cpp.dolfin_error("bcs.py",
                                 "create DirichletBC",
                                 "Expecting a DirichleBC as only argument"\
                                 " for copy constructor")

            # Initialize base class
            cpp.DirichletBC.__init__(self, args[0])
            self.domain_args = args[0].domain_args
            return

        # Special case for value specified as float, tuple or similar
        if len(args) >= 2 and not isinstance(args[1], cpp.GenericFunction):
            if isinstance(args[1], ufl.classes.Expr):
                expr = project(args[1], args[0])
            else:
                expr = Constant(args[1])  # let Constant handle all problems
            args = args[:1] + (expr, ) + args[2:]

        # Special case for sub domain specified as a function
        if len(args) >= 3 and isinstance(args[2], types.FunctionType):
            sub_domain = AutoSubDomain(args[2])
            args = args[:2] + (sub_domain, ) + args[3:]

        # Special case for sub domain specified as a string
        if len(args) >= 3 and isinstance(args[2], str):
            sub_domain = CompiledSubDomain(args[2])
            args = args[:2] + (sub_domain, ) + args[3:]

        # Store Expression to avoid scoping issue with SWIG directors
        if isinstance(args[1], cpp.Expression):
            self.function_arg = args[1]

        # Store SubDomain to avoid scoping issue with SWIG directors
        self.domain_args = args[2:]

        # FIXME: Handling of multiple default arguments does not
        # really work between Python and C++ when C++ requires them to
        # be ordered and cannot accept the latter without the
        # former...

        # Add keyword arguments (in correct order...)
        allowed_kwargs = ["method", "check_midpoint"]
        for key in allowed_kwargs:
            if key in kwargs:
                args = tuple(list(args) + [kwargs[key]])

        # Check for other keyword arguments
        for key in kwargs:
            if not key in allowed_kwargs:
                cpp.dolfin_error("bcs.py", "create boundary condition",
                                 "Unknown keyword argument \"%s\"" % key)

        # Initialize base class
        cpp.DirichletBC.__init__(self, *args)
Exemple #20
0
def _extract_u(u):
    "Extract and check argument u"
    if not isinstance(u, cpp.Function):
        cpp.dolfin_error("solving.py",
                         "solve variational problem",
                         "Expecting second argument to be a Function")
    return u
Exemple #21
0
def adjoint(form, reordered_arguments=None):

    # Call UFL directly if new arguments are provided directly
    if reordered_arguments is not None:
        return ufl.adjoint(form, reordered_arguments=reordered_arguments)

    # Extract form arguments
    arguments = form.arguments()
    if any(arg.part() is not None for arg in arguments):
        cpp.dolfin_error("formmanipulation.py",
                         "compute adjoint of form",
                         "parts not supported")
    if not (len(arguments) == 2):
        cpp.dolfin_error("formmanipulation.py",
                         "compute adjoint of form",
                         "Form is not bilinear")

    # Define new Argument(s) in the same spaces (NB: Order does not
    # matter anymore here because number is absolute)
    v_1 = Argument(arguments[1].function_space(), arguments[0].number(),
                   arguments[0].part())
    v_0 = Argument(arguments[0].function_space(), arguments[1].number(),
                   arguments[1].part())

    # Call ufl.adjoint with swapped arguments as new arguments
    return ufl.adjoint(form, reordered_arguments=(v_1, v_0))
    def extract_sub_space(self, component):
        """
        Extract subspace for component

        *Arguments*
            component (numpy.array(uint))
               The component.

        *Returns*
            _FunctionSpace_
                The subspace.
        """

        # Transform the argument to a NumPy array
        if not hasattr(component, "__len__"):
            cpp.dolfin_error("functionspace.py",
                             "extracting sub spaces",
                             "Expected a component which is iterable")
        component = numpy.asarray(component, dtype=numpy.uintp)

        # Get the cpp version of the FunctionSpace
        cpp_space = cpp.FunctionSpace.extract_sub_space(self, component)

        # Instantiate a ufl finite element based on the dolfin element signature
        element = eval(cpp_space.element().signature(), ufl.__dict__)
        return FunctionSpaceFromCpp(cpp_space, element)
Exemple #23
0
def derivative(form, u, du=None, coefficient_derivatives=None):
    if du is None:
        # Get existing arguments from form and position the new one with the next argument number
        from ufl.algorithms import extract_arguments
        form_arguments = extract_arguments(form)

        number = max([-1] + [arg.number() for arg in form_arguments]) + 1

        if any(arg.part() is not None for arg in form_arguments):
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create third argument using parts, please supply one"
            )
        part = None

        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V, number, part)
        elif isinstance(u, (list, tuple)) and all(
                isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V, number, part))
        else:
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create third argument, please supply one"
            )
    return ufl.derivative(form, u, du, coefficient_derivatives)
Exemple #24
0
def MultiMeshFunctionSpace(multimesh, family, degree=None):
    """Create multimesh finite element function space.

    *Arguments*
        multimesh
            a :py:class:`MultiMesh <dolfin.cpp.MultiMesh>`.
        family
            a string specifying the element family,
            see :py:class:`FunctionSpace
            <dolfin.functions.functionspace.FunctionSpace>`
            for alternatives.

            This argument may also be a `FiniteElement`, in
            which case the `degree` argument should not be
            specified.
        degree
            the degree of the element.

    *Example of usage*

        .. code-block:: python

            V = MultiMeshFunctionSpace(mesh, "CG", 1)

            element = FiniteElement("Lagrange", triangle, 1)
            V = MultiMeshFunctionSpace(mesh, element)

    Note: Multimesh function spaces does currently not support
    function space algebra. For this reason, mixed function spaces
    and the like must be created via a finite element.
    """

    # Check arguments
    if not isinstance(multimesh, cpp.MultiMesh):
        cpp.dolfin_error(
            "functionspace.py", "create multimesh function space",
            "Illegal argument, not a multimesh: " + str(multimesh))

    # Create element if not supplied
    if isinstance(family, ufl.FiniteElementBase):
        element = family
    else:
        mesh = multimesh.part(0)
        element = ufl.FiniteElement(family, mesh.ufl_cell(), degree)

    # Create and add individual function spaces
    V = cpp.MultiMeshFunctionSpace(multimesh)
    V_parts = []
    for part in range(multimesh.num_parts()):
        V_part = FunctionSpace(multimesh.part(part), element)
        V_parts.append(V_part)
        V.add(V_part)

    # Build multimesh function space
    V.build()

    # Store full function spaces
    V._parts = V_parts

    return V
Exemple #25
0
def expect_arg(argtype, arg, argname):
    # Check the type of the argument
    if isinstance(arg, argtype):
        return

    cpp.dolfin_error("compilemodule.py",
                     "ensure correct argument for compile_extension_module",
                     "Provide a '%s', for the '%s' argument" % \
                     (argtype.__name__, argname))
Exemple #26
0
def check_swig_version(compiled_module):

    # Check swig version of compiled module
    if compiled_module and compiled_module.swigversion != cpp.__swigversion__:
        cpp.dolfin_error("compilemodule.py",
                         "compiling extension module",
                         "Incompatible swig versions detected. DOLFIN swig "\
                         "version is not the same as extension module swig "\
                         "version: '%s' != '%s' " % \
                         (cpp.__swigversion__, compiled_module.swigversion))
Exemple #27
0
def _solve_varproblem_adaptive(*args, **kwargs):
    "Solve variational problem a == L or F == 0 adaptively"

    # Extract arguments
    eq, u, bcs, J, tol, M, form_compiler_parameters, \
        solver_parameters = _extract_args(*args, **kwargs)

    print('eq.lhs = ', eq.lhs, ' eq.rhs=', eq.rhs)

    # Check that we received the goal functional
    if M is None:
        cpp.dolfin_error("solving.py", "solve variational problem adaptively",
                         "Missing goal functional")

    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        # Create problem
        problem = LinearVariationalProblem(
            eq.lhs,
            eq.rhs,
            u,
            bcs,
            form_compiler_parameters=form_compiler_parameters)

        # Create solver and call solve
        solver = AdaptiveLinearVariationalSolver(problem, M)
        solver.parameters.update(solver_parameters)
        solver.solve(tol)

    # Solve nonlinear variational problem
    else:

        # Create Jacobian if missing
        if J is None:
            cpp.log.info(
                "No Jacobian form specified for nonlinear variational problem."
            )
            cpp.log.info(
                "Differentiating residual form F to obtain Jacobian J = F'.")
            F = eq.lhs
            J = derivative(F, u)

        # Create problem
        problem = NonlinearVariationalProblem(
            eq.lhs,
            u,
            bcs,
            J,
            form_compiler_parameters=form_compiler_parameters)

        # Create solver and call solve
        solver = AdaptiveNonlinearVariationalSolver(problem, M)
        solver.parameters.update(solver_parameters)
        solver.solve(tol)
Exemple #28
0
    def assign(self, rhs):
        """
        Assign either a Function or linear combination of Functions.

        *Arguments*
            rhs (_Function_)
                A Function or a linear combination of Functions. If a linear
                combination is passed all Functions need to be in the same
                FunctionSpaces.
        """
        from ufl.classes import ComponentTensor, Sum, Product, Division

        if isinstance(rhs, (cpp.Function, cpp.Expression, cpp.FunctionAXPY)):
            # Avoid self assignment
            if self == rhs:
                return

            self._assign(rhs)
        elif isinstance(rhs, (Sum, Product, Division, ComponentTensor)):
            if isinstance(rhs, ComponentTensor):
                rhs, multi_index = rhs.ufl_operands
            else:
                multi_index = None
            linear_comb = _check_and_contract_linear_comb(rhs, self, multi_index)
            assert linear_comb

            # If the assigned Function lives in a different FunctionSpace
            # we cannot operate on this function directly
            same_func_space = linear_comb[0][0] in self.function_space()
            func, weight = linear_comb.pop()

            # Assign values from first func
            if not same_func_space:
                self._assign(func)
                vector = self.vector()
            else:
                vector = self.vector()
                vector[:] = func.vector()

            # If first weight is not 1 scale
            if weight != 1.0:
                vector *= weight

            # AXPY the other functions
            for func, weight in linear_comb:
                if weight == 0.0:
                    continue
                vector.axpy(weight, func.vector())

        else:
            cpp.dolfin_error(
                "function.py",
                "function assignment",
                "Expects a Function or linear combinations of " "Functions in the same FunctionSpaces",
            )
Exemple #29
0
    def __new__(cls, cppV, element=None):
        if not isinstance(cppV, (cpp.FunctionSpace)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a cpp.FunctionSpace: " + str(cppV))

        # Lets be agressive in abusing dynamic typing shall we...
        cppV._dolfin_element = cppV.element()
        cppV._ufl_element = eval(cppV.element().signature(), ufl.__dict__).reconstruct(domain=cppV.mesh())
        cppV.__class__ = FunctionSpaceBase
        return cppV
Exemple #30
0
    def assign(self, rhs):
        """
        Assign either a Function or linear combination of Functions.

        *Arguments*
            rhs (_Function_)
                A Function or a linear combination of Functions. If a linear
                combination is passed all Functions need to be in the same
                FunctionSpaces.
        """
        from ufl.classes import ComponentTensor, Sum, Product, Division
        if isinstance(rhs, (cpp.Function, cpp.Expression, cpp.FunctionAXPY)):
            # Avoid self assignment
            if self == rhs:
                return

            self._assign(rhs)
        elif isinstance(rhs, (Sum, Product, Division, ComponentTensor)):
            if isinstance(rhs, ComponentTensor):
                rhs, multi_index = rhs.ufl_operands
            else:
                multi_index = None
            linear_comb = _check_and_contract_linear_comb(rhs, self, \
                                                          multi_index)
            assert (linear_comb)

            # If the assigned Function lives in a different FunctionSpace
            # we cannot operate on this function directly
            same_func_space = linear_comb[0][0] in self.function_space()
            func, weight = linear_comb.pop()

            # Assign values from first func
            if not same_func_space:
                self._assign(func)
                vector = self.vector()
            else:
                vector = self.vector()
                vector[:] = func.vector()

            # If first weight is not 1 scale
            if weight != 1.0:
                vector *= weight

            # AXPY the other functions
            for func, weight in linear_comb:
                if weight == 0.0:
                    continue
                vector.axpy(weight, func.vector())

        else:
            cpp.dolfin_error("function.py",
                             "function assignment",
                             "Expects a Function or linear combinations of "\
                             "Functions in the same FunctionSpaces")
Exemple #31
0
def _extract_bcs(bcs):
    "Extract and check argument bcs"
    if bcs is None:
        bcs = []
    elif not isinstance(bcs, (list, tuple)):
        bcs = [bcs]
    for bc in bcs:
        if not isinstance(bc, cpp.DirichletBC):
            cpp.dolfin_error("solving.py", "solve variational problem",
                             "Unable to extract boundary condition arguments")
    return bcs
    def __new__(cls, cppV, element=None):
        if not isinstance(cppV, (cpp.FunctionSpace)):
            cpp.dolfin_error("functionspace.py",
                             "create function space",
                             "Illegal argument, not a cpp.FunctionSpace: " + str(cppV))

        # Lets be agressive in abusing dynamic typing shall we...
        cppV._dolfin_element = cppV.element()
        cppV._ufl_element = eval(cppV.element().signature(), ufl.__dict__).reconstruct(domain=cppV.mesh())
        cppV.__class__ = FunctionSpaceBase
        return cppV
Exemple #33
0
def expect_list_of(argtype, arg, argname):
    if arg is None:
        return []

    if isinstance(arg, (types.NoneType, list, tuple)):
        if all(isinstance(s, argtype) for s in arg):
            return arg

    cpp.dolfin_error("compilemodule.py",
                     "ensure correct argument for compile_extension_module",
                     "Provide a 'tuple' or 'list' with '%s', for the "\
                     "'%s' argument" % (argtype.__name__, argname))
Exemple #34
0
def _extract_bcs(bcs):
    "Extract and check argument bcs"
    if bcs is None:
        bcs = []
    elif not isinstance(bcs, (list, tuple)):
        bcs = [bcs]
    for bc in bcs:
        if not isinstance(bc, cpp.DirichletBC):
            cpp.dolfin_error("solving.py",
                             "solve variational problem",
                             "Unable to extract boundary condition arguments")
    return bcs
Exemple #35
0
def init_parent_edge_indices(submesh, mesh):
    "Initialize data 'parent_edge_indices' for submesh."

    # Check arguments
    if not isinstance(submesh, Mesh):
        raise TypeError, "expected 'Mesh' as argument"
    if not isinstance(mesh, Mesh):
        raise TypeError, "expected 'Mesh' as argument"

    # Check if edge map has already been computed
    if not submesh.data().mesh_function("parent_edge_indices") is None:
        info("Edge map 'parent_edge_indices' already computed, not computing again.")

    # Get parent vertex numbers
    parent_vertex_indices = submesh.data().mesh_function("parent_vertex_indices")
    if parent_vertex_indices is None:
        cpp.dolfin_error("ale.py",
                         "initialize parent edge indices",
                         "Parent vertex indice are missing")

    # Make sure that we have edges for both meshes
    submesh.init(1)
    mesh.init(1)

    # Make sure we have vertex-edge connectivity for parent mesh
    mesh.init(0, 1)

    # Create the edge map
    parent_edge_indices = submesh.data().create_mesh_function("parent_edge_indices")
    parent_edge_indices.init(1)

    # Iterate over the edges and figure out their parent number
    for local_edge in edges(submesh):

        # Get parent indices for edge vertices
        v0, v1 = local_edge.entities(0)
        V0 = Vertex(mesh, parent_vertex_indices[int(v0)])
        V1 = Vertex(mesh, parent_vertex_indices[int(v1)])

        # Get outgoing edges from the two parent vertices
        edges0 = set(V0.entities(1))
        edges1 = set(V1.entities(1))

        # Check intersection
        common_edges = edges0.intersection(edges1)
        if not len(common_edges) == 1:
            cpp.dolfin_error("ale.py",
                             "initialize parent edge indices",
                             "Parent vertices do not share exactly one common edge")
        parent_edge_index = list(common_edges)[0]

        # Set value
        parent_edge_indices[local_edge.index()] = parent_edge_index
Exemple #36
0
def init_parent_edge_indices(submesh, mesh):
    "Initialize data 'parent_edge_indices' for submesh."

    # Check arguments
    if not isinstance(submesh, Mesh):
        raise TypeError("expected 'Mesh' as argument")
    if not isinstance(mesh, Mesh):
        raise TypeError("expected 'Mesh' as argument")

    # Check if edge map has already been computed
    if not submesh.data().exists("parent_edge_indices", 1):
        info(
            "Edge map 'parent_edge_indices' already computed, not computing again."
        )

    # Get parent vertex numbers
    parent_vertex_indices = submesh.data().array("parent_vertex_indices", 0)
    if parent_vertex_indices is None:
        cpp.dolfin_error("ale.py", "initialize parent edge indices",
                         "Parent vertex indice are missing")

    # Make sure that we have edges for both meshes
    submesh.init(1)
    mesh.init(1)

    # Make sure we have vertex-edge connectivity for parent mesh
    mesh.init(0, 1)

    # Create the edge map
    parent_edge_indices = submesh.data().create_array("parent_edge_indices", 1)

    # Iterate over the edges and figure out their parent number
    for local_edge in edges(submesh):

        # Get parent indices for edge vertices
        v0, v1 = local_edge.entities(0)
        V0 = Vertex(mesh, parent_vertex_indices[int(v0)])
        V1 = Vertex(mesh, parent_vertex_indices[int(v1)])

        # Get outgoing edges from the two parent vertices
        edges0 = set(V0.entities(1))
        edges1 = set(V1.entities(1))

        # Check intersection
        common_edges = edges0.intersection(edges1)
        if not len(common_edges) == 1:
            cpp.dolfin_error(
                "ale.py", "initialize parent edge indices",
                "Parent vertices do not share exactly one common edge")
        parent_edge_index = list(common_edges)[0]

        # Set value
        parent_edge_indices[local_edge.index()] = parent_edge_index
Exemple #37
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)
Exemple #38
0
    def __init__(self, mesh):
        "Create function that evaluates to the mesh coordinates at each vertex."
        # Initialize C++ part
        cpp.MeshCoordinates.__init__(self, mesh)

        # Initialize UFL part
        ufl_element = mesh.ufl_domain().ufl_coordinate_element()
        if ufl_element.family() != "Lagrange" or ufl_element.degree() != 1:
            cpp.dolfin_error("specialfunctions.py",
                             "initialize MeshCoordinates",
                             "dolfin::MeshCoordinates only supports affine meshes")
        ufl_function_space = ufl.FunctionSpace(mesh.ufl_domain(), ufl_element)
        ufl.Coefficient.__init__(self, ufl_function_space, count=self.id())
Exemple #39
0
    def __init__(self, mesh):
        "Create function that evaluates to the mesh coordinates at each vertex."
        # Initialize C++ part
        cpp.MeshCoordinates.__init__(self, mesh)

        # Initialize UFL part
        ufl_element = mesh.ufl_domain().ufl_coordinate_element()
        if ufl_element.family() != "Lagrange" or ufl_element.degree() != 1:
            cpp.dolfin_error("specialfunctions.py",
                             "initialize MeshCoordinates",
                             "dolfin::MeshCoordinates only supports affine meshes")
        ufl_function_space = ufl.FunctionSpace(mesh.ufl_domain(), ufl_element)
        ufl.Coefficient.__init__(self, ufl_function_space, count=self.id())
Exemple #40
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 derivative(form, u, du=None):
    if du is None:
        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V)
        elif isinstance(u, (list,tuple)) and all(isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V))
        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form",
                             "Cannot automatically create third argument, please supply one")

    return ufl.derivative(form, u, du)
Exemple #42
0
    def mpi_jit(*args, **kwargs):

        # FIXME: should require mpi_comm to be explicit
        # and not default to comm_world?
        mpi_comm = kwargs.pop("mpi_comm", cpp.MPI.comm_world)

        # Just call JIT compiler when running in serial
        if cpp.MPI.size(mpi_comm) == 1:
            return local_jit(*args, **kwargs)

        # Default status (0 == ok, 1 == fail)
        status = 0

        # Compile first on process 0
        root = cpp.MPI.rank(mpi_comm) == 0
        if root:
            try:
                output = local_jit(*args, **kwargs)
            except Exception as e:
                status = 1
                error_msg = str(e)

        # TODO: This would have lower overhead if using the dijitso.jit
        # features to inject a waiting callback instead of waiting out
        # here. That approach allows all processes to first look in the
        # cache, introducing a barrier only on cache miss. There's also
        # a sketch in dijitso of how to make only one process per
        # physical cache directory do the compilation.

        # Wait for the compiling process to finish and get status
        # TODO: Would be better to broadcast the status from root but
        # this works.
        global_status = cpp.MPI.max(mpi_comm, status)

        if global_status == 0:
            # Success, call jit on all other processes (this should just
            # read the cache)
            if not root:
                output = local_jit(*args, **kwargs)
        else:
            # Fail simultaneously on all processes, to allow catching
            # the error without deadlock
            if not root:
                error_msg = "Compilation failed on root node."
            cpp.dolfin_error("jit.py",
                             "perform just-in-time compilation of form",
                             error_msg)
        return output
Exemple #43
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 derivative(form, u, du=None):
    if du is None:
        if isinstance(u, Function):
            V = u.function_space()
            du = Argument(V)
        elif isinstance(u, (list, tuple)) and all(
                isinstance(w, Function) for w in u):
            V = MixedFunctionSpace([w.function_space() for w in u])
            du = ufl.split(Argument(V))
        else:
            cpp.dolfin_error(
                "formmanipulation.py", "compute derivative of form",
                "Cannot automatically create third argument, please supply one"
            )

    return ufl.derivative(form, u, du)
Exemple #45
0
def jit(form, form_compiler_parameters=None, mpi_comm=None):
    """Just-in-time compile any provided form.

    It uses the jit function from the form compiler registered by
    parameters["form_compiler"]["name"].
    """

    # Check that form is not empty
    if isinstance(form, ufl.Form):
        if form.empty():
            raise RuntimeError("Form is empty. Cannot pass to JIT compiler.")

    # Import form compiler
    form_compiler_name = cpp.parameters["form_compiler"]["name"]
    try:
        form_compiler = __import__(form_compiler_name)
    except ImportError as message:
        print(message)
        warning("Could not import %s form compiler, falling back to FFC." \
                % form_compiler_name)
        try:
            form_compiler = __import__("ffc")
        except:
            cpp.dolfin_error("jit.py",
                             "perform just-in-time compilation of form",
                             "Could not import FFC form compiler")

    # Checks on form compiler interface
    if not (hasattr(form_compiler, 'default_parameters')
            and hasattr(form_compiler, 'jit')):
        raise RuntimeError(
            "Form compiler must implement the default_parameters and jit functions."
        )

    # Prepare form compiler parameters
    p = form_compiler.default_parameters()

    # Set parameters from global DOLFIN parameter set
    for key, value in six.iteritems(parameters["form_compiler"]):
        p[key] = value

    # Override with local parameters if any
    if form_compiler_parameters:
        p.update(form_compiler_parameters)

    # Execute!
    return form_compiler.jit(form, parameters=p)
Exemple #46
0
def MixedFunctionSpace(spaces):
    """
    Create mixed finite element function space.

    *Arguments*
        spaces
            a list (or tuple) of :py:class:`FunctionSpaces
            <dolfin.functions.functionspace.FunctionSpace>`.

    *Examples of usage*
        The function space may be created by

        .. code-block:: python

            V = MixedFunctionSpace(spaces)

        ``spaces`` may consist of multiple occurances of the same space:

        .. code-block:: python

            P1  = FunctionSpace(mesh, "CG", 1)
            P2v = VectorFunctionSpace(mesh, "Lagrange", 2)

            ME  = MixedFunctionSpace([P2v, P1, P1, P1])

    """
    cpp.deprecation("'MixedFunctionSpace'", "1.7.0", "2.0.0",
                    "Use 'FunctionSpace(mesh, MixedElement(...))'.")

    # Check arguments
    if not len(spaces) > 0:
        cpp.dolfin_error("functionspace.py",
                         "create mixed function space",
                         "Need at least one subspace")
    if not all(isinstance(V, FunctionSpace) for V in spaces):
        cpp.dolfin_error("functionspace.py",
                         "create mixed function space",
                         "Invalid subspaces: " + str(spaces))

    # Get common mesh and constrained_domain, must all be the same
    mesh, constrained_domain = _get_common_mesh_and_constrained_domain(spaces)

    # Create UFL element
    element = ufl.MixedElement(*[V.ufl_element() for V in spaces])

    return FunctionSpace(mesh, element,
                         constrained_domain=constrained_domain)
Exemple #47
0
    def __init__(self, spaces):
        """
        Create mixed finite element function space.

        *Arguments*
            spaces
                a list (or tuple) of :py:class:`FunctionSpaces
                <dolfin.functions.functionspace.FunctionSpace>`.

        *Examples of usage*
            The function space may be created by

            .. code-block:: python

                V = MixedFunctionSpace(spaces)

            ``spaces`` may consist of multiple occurances of the same space:

            .. code-block:: python

                P1  = FunctionSpace(mesh, "CG", 1)
                P2v = VectorFunctionSpace(mesh, "Lagrange", 2)

                ME  = MixedFunctionSpace([P2v, P1, P1, P1])

        """

        # Check arguments
        if not len(spaces) > 0:
            cpp.dolfin_error("functionspace.py",
                             "create mixed function space",
                             "Need at least one subspace")
        if not all(isinstance(V, FunctionSpaceBase) for V in spaces):
            cpp.dolfin_error("functionspace.py",
                             "create mixed function space",
                             "Invalid subspaces: " + str(spaces))

        # Create UFL element
        element = ufl.MixedElement(*[V.ufl_element() for V in spaces])

        # Get common mesh and constrained_domain, must all be the same
        mesh, constrained_domain \
        = _get_common_mesh_and_constrained_domain(spaces, "mixed")

        # Initialize base class using mesh from first space
        FunctionSpaceBase.__init__(self, mesh, element, \
                                   constrained_domain=constrained_domain)
    def __init__(self, spaces):
        """
        Create mixed finite element function space.

        *Arguments*
            spaces
                a list (or tuple) of :py:class:`FunctionSpaces
                <dolfin.functions.functionspace.FunctionSpace>`.

        *Examples of usage*
            The function space may be created by

            .. code-block:: python

                V = MixedFunctionSpace(spaces)

            ``spaces`` may consist of multiple occurances of the same space:

            .. code-block:: python

                P1  = FunctionSpace(mesh, "CG", 1)
                P2v = VectorFunctionSpace(mesh, "Lagrange", 2)

                ME  = MixedFunctionSpace([P2v, P1, P1, P1])

        """

        # Check arguments
        if not len(spaces) > 0:
            cpp.dolfin_error("functionspace.py",
                             "create mixed function space",
                             "Need at least one subspace")
        if not all(isinstance(V, FunctionSpaceBase) for V in spaces):
            cpp.dolfin_error("functionspace.py",
                             "create mixed function space",
                             "Invalid subspaces: " + str(spaces))
        #if not all(V.mesh() == spaces[0].mesh() for V in spaces):
        #    cpp.dolfin_error("functionspace.py", "Nonmatching meshes for mixed function space: " \
        #              + str([V.mesh() for V in spaces]))

        # Check that all spaces share same constrained_domain map

        # Create UFL element
        element = ufl.MixedElement(*[V.ufl_element() for V in spaces])

        # Initialize base class using mesh from first space
        FunctionSpaceBase.__init__(self, spaces[0].mesh(), element, constrained_domain=spaces[0].dofmap().constrained_domain)
Exemple #49
0
def jit(form, form_compiler_parameters=None, common_cell=None):
    """Just-in-time compile any provided form.

    It uses the jit function from the form compiler registered by
    parameters["form_compiler"]["name"].
    """

    # Check that form is not empty
    if isinstance(form, ufl.Form):
        if form.integrals() == ():
            raise RuntimeError, "Form is empty. Cannot pass to JIT compiler."

    global _swig_version_ok

    # Check and set swig binary
    if not _swig_version_ok and not check_and_set_swig_binary(\
        parameters["swig_binary"], parameters["swig_path"]):
        raise OSError, "Could not find swig installation. Pass an existing "\
              "swig binary or install SWIG version 2.0 or higher.\n"

    # Check that the form compiler will use the same swig version
    # that PyDOLFIN was compiled with
    _swig_version_ok = _swig_version_ok or \
                       check_swig_version(cpp.__swigversion__, same=True)

    if not _swig_version_ok:
        raise OSError, """\
PyDOLFIN was not compiled with the present version of swig.
Install swig version %s or recompiled PyDOLFIN with present swig
"""%cpp.__swigversion__

    # Cache swig version test
    _swig_version_ok = True

    # Import form compiler
    form_compiler_name = cpp.parameters["form_compiler"]["name"]
    try:
        form_compiler = __import__(form_compiler_name)
    except ImportError, message:
        print message
        warning("Could not import %s form compiler, falling back to FFC." % form_compiler_name)
        try:
            form_compiler = __import__("ffc")
        except:
            cpp.dolfin_error("jit.py",
                             "perform just-in-time compilation of form",
                             "Could not import FFC form compiler")
Exemple #50
0
def compute_vertex_map(mesh0, mesh1):
    """
    Compute map from vertices of mesh0 to vertices of mesh1.

    *Arguments*
        mesh0
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.
        mesh1
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.

    It is assumed that both meshes have a :py:class:`MeshFunction
    <dolfin.cpp.MeshFunction>` over the vertices named
    "parent_vertex_indices" which contain a mapping from the
    local vertices to a common parent vertex numbering.

    """

    # Check arguments
    if not isinstance(mesh0, Mesh):
        raise TypeError, "expected 'Mesh' as argument"
    if not isinstance(mesh1, Mesh):
        raise TypeError, "expected 'Mesh' as argument"

    # Get parent vertex numbers
    vertices0 = mesh0.data().array("parent_vertex_indices", 0)
    vertices1 = mesh1.data().array("parent_vertex_indices", 0)

    # Check mappings
    if vertices0 is None or vertices1 is None:
        cpp.dolfin_error("ale.py",
                         "compute vertex map",
                         "Parent vertex indices are missing")

    # Compute parent-to-local mapping for mesh1
    parent_to_local_mesh1 = {}
    for i in range(len(vertices1)):
        parent_to_local_mesh1[vertices1[i]] = i

    # Compute local-to-local mapping
    vertex_map = {}
    for i in range(vertices0.size):
        parent_vertex = vertices0[i]
        if parent_vertex in parent_to_local_mesh1:
            vertex_map[i] = parent_to_local_mesh1[parent_vertex]

    return vertex_map
Exemple #51
0
    def __init__(self, *args, **kwargs):
        "Create Dirichlet boundary condition"

        # Copy constructor
        if len(args) == 1:
            if not isinstance(args[0], cpp.DirichletBC):
                cpp.dolfin_error("bcs.py",
                                 "create DirichletBC",
                                 "Expecting a DirichleBC as only argument"\
                                 " for copy constructor")

            # Initialize base class
            cpp.DirichletBC.__init__(self, args[0])
            return

        # Special case for value specified as float, tuple or similar
        if len(args) >= 2 and not isinstance(args[1], cpp.GenericFunction):
            if isinstance(args[1], ufl.classes.Expr):
                expr = project(args[1], args[0])
            else:
                expr = Constant(args[1]) # let Constant handle all problems
            args = args[:1] + (expr,) + args[2:]

        # Special case for sub domain specified as a function
        if len(args) >= 3 and isinstance(args[2], types.FunctionType):
            sub_domain = AutoSubDomain(args[2])
            args = args[:2] + (sub_domain,) + args[3:]

        # Special case for sub domain specified as a string
        if len(args) >= 3 and isinstance(args[2], str):
            sub_domain = compile_subdomains(args[2])
            args = args[:2] + (sub_domain,) + args[3:]

        # Store Expression to avoid scoping issue with SWIG directors
        if isinstance(args[1], cpp.Expression):
            self.function_arg = args[1]

        # Store SubDomain to avoid scoping issue with SWIG directors
        self.domain_args = args[2:]

        # Add method argument if it's given
        if "method" in kwargs:
            args = tuple(list(args) + [kwargs["method"]])

        # Initialize base class
        cpp.DirichletBC.__init__(self, *args)
Exemple #52
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
Exemple #53
0
def compute_vertex_map(mesh0, mesh1):
    """
    Compute map from vertices of mesh0 to vertices of mesh1.

    *Arguments*
        mesh0
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.
        mesh1
            a :py:class:`Mesh <dolfin.cpp.Mesh>`.

    It is assumed that both meshes have a :py:class:`MeshFunction
    <dolfin.cpp.MeshFunction>` over the vertices named
    "parent_vertex_indices" which contain a mapping from the
    local vertices to a common parent vertex numbering.

    """

    # Check arguments
    if not isinstance(mesh0, cpp.mesh.Mesh) or not isinstance(
            mesh1, cpp.mesh.Mesh):
        cpp.dolfin_error("ale.py", "compute vertex map",
                         "Expected 'Mesh' as argument")

    # Get parent vertex numbers
    vertices0 = mesh0.data().array("parent_vertex_indices", 0)
    vertices1 = mesh1.data().array("parent_vertex_indices", 0)

    # Check mappings
    if vertices0 is None or vertices1 is None:
        cpp.dolfin_error("ale.py", "compute vertex map",
                         "Parent vertex indices are missing")

    # Compute parent-to-local mapping for mesh1
    parent_to_local_mesh1 = {}
    for i in range(len(vertices1)):
        parent_to_local_mesh1[vertices1[i]] = i

    # Compute local-to-local mapping
    vertex_map = {}
    for i in range(vertices0.size):
        parent_vertex = vertices0[i]
        if parent_vertex in parent_to_local_mesh1:
            vertex_map[i] = parent_to_local_mesh1[parent_vertex]

    return vertex_map
Exemple #54
0
    def __init__(self, inside_function):
        "Create SubDomain subclass for given inside() function"

        # Check that we get a function
        if not isinstance(inside_function, types.FunctionType):
            cpp.dolfin_error("bcs.py",
                             "auto-create subdomain",
                             "Expecting a function (not %s)" % \
                                 str(type(inside_function)))
        self.inside_function = inside_function

        # Check the number of arguments
        if not inside_function.func_code.co_argcount in (1, 2):
            cpp.dolfin_error("bcs.py",
                             "auto-create subdomain",
                             "Expecting a function of the form inside(x) or inside(x, on_boundary)")
        self.num_args = inside_function.func_code.co_argcount

        cpp.SubDomain.__init__(self)
    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)