Ejemplo n.º 1
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
def _plot_matplotlib(obj, mesh, kwargs):
    if isinstance(obj, (cpp.MultiMesh, cpp.MultiMeshFunction, cpp.MultiMeshDirichletBC)):
        cpp.warning("Don't know how to plot type %s" % type(obj))
        return

    # Avoid importing pyplot until used
    try:
        import matplotlib.pyplot as plt
    except:
        print("*** Warning: matplotlib.pyplot not available, cannot plot")
        return

    gdim = mesh.geometry().dim()
    if gdim == 3 or kwargs.get("mode") in ("warp",):
        # Importing this toolkit has side effects enabling 3d support
        from mpl_toolkits.mplot3d import axes3d
        # Enabling the 3d toolbox requires some additional arguments
        ax = plt.gca(projection='3d')
    else:
        ax = plt.gca()
    ax.set_aspect('equal')

    title = kwargs.pop("title", None)
    if title is not None:
        ax.set_title(title)

    # Translate range_min/max kwargs supported by VTKPlotter
    vmin = kwargs.pop("range_min", None)
    vmax = kwargs.pop("range_max", None)
    if vmin and not "vmin" in kwargs:
        kwargs["vmin"] = vmin
    if vmax and not "vmax" in kwargs:
        kwargs["vmax"] = vmax

    # Let's stays consistent and use mode='color' instead of 'surface'
    if kwargs.get("mode") == "surface":
        cpp.deprecation("plot kwarg mode='surface'", "2016.1",
                        "Use mode='color' instead.")
        kwargs["mode"] = "color"

    # Drop unsupported kwargs and inform user
    _unsupported_kwargs = ["interactive", "rescale", "wireframe"]
    for kw in _unsupported_kwargs:
        if kwargs.pop(kw, None):
            cpp.warning("Matplotlib backend does not support '%s' kwarg yet. "
                        "Ignoring it..." % kw)

    if isinstance(obj, cpp.Function):
        return mplot_function(ax, obj, **kwargs)
    elif isinstance(obj, cpp.Expression):
        return mplot_expression(ax, obj, mesh, **kwargs)
    elif isinstance(obj, cpp.Mesh):
        return mplot_mesh(ax, obj, **kwargs)
    elif isinstance(obj, cpp.DirichletBC):
        return mplot_dirichletbc(ax, obj, **kwargs)
    elif isinstance(obj, _meshfunction_types):
        return mplot_meshfunction(ax, obj, **kwargs)
    else:
        raise AttributeError('Failed to plot %s' % type(obj))
Ejemplo n.º 4
0
def _plot_matplotlib(obj, mesh, kwargs):
    if isinstance(obj, (cpp.MultiMesh, cpp.MultiMeshFunction, cpp.MultiMeshDirichletBC)):
        cpp.warning("Don't know how to plot type %s" % type(obj))
        return

    # Avoid importing pyplot until used
    try:
        import matplotlib.pyplot as plt
    except:
        print("*** Warning: matplotlib.pyplot not available, cannot plot")
        return

    gdim = mesh.geometry().dim()
    if gdim == 3 or kwargs.get("mode") in ("warp",):
        # Importing this toolkit has side effects enabling 3d support
        from mpl_toolkits.mplot3d import axes3d
        # Enabling the 3d toolbox requires some additional arguments
        ax = plt.gca(projection='3d')
    else:
        ax = plt.gca()
    ax.set_aspect('equal')

    title = kwargs.pop("title", None)
    if title is not None:
        ax.set_title(title)

    # Translate range_min/max kwargs supported by VTKPlotter
    vmin = kwargs.pop("range_min", None)
    vmax = kwargs.pop("range_max", None)
    if vmin and not "vmin" in kwargs:
        kwargs["vmin"] = vmin
    if vmax and not "vmax" in kwargs:
        kwargs["vmax"] = vmax

    # Let's stays consistent and use mode='color' instead of 'surface'
    if kwargs.get("mode") == "surface":
        cpp.deprecation("plot kwarg mode='surface'", "1.7.0", "1.7.0",
                        "Use mode='color' instead.")
        kwargs["mode"] = "color"

    # Drop unsupported kwargs and inform user
    _unsupported_kwargs = ["interactive", "rescale", "wireframe"]
    for kw in _unsupported_kwargs:
        if kwargs.pop(kw, None):
            cpp.warning("Matplotlib backend does not support '%s' kwarg yet. "
                        "Ignoring it..." % kw)

    if isinstance(obj, cpp.Function):
        return mplot_function(ax, obj, **kwargs)
    elif isinstance(obj, cpp.Expression):
        return mplot_expression(ax, obj, mesh, **kwargs)
    elif isinstance(obj, cpp.Mesh):
        return mplot_mesh(ax, obj, **kwargs)
    elif isinstance(obj, cpp.DirichletBC):
        return mplot_dirichletbc(ax, obj, **kwargs)
    elif isinstance(obj, _meshfunction_types):
        return mplot_meshfunction(ax, obj, **kwargs)
    else:
        raise AttributeError('Failed to plot %s' % type(obj))
Ejemplo n.º 5
0
    def __init__(self, *args, **kwargs):
        """Initialize Function."""
        # Initial quick check for valid arguments (other checks sprinkled below)
        if len(args) == 0:
            raise TypeError("expected 1 or more arguments")

        # Type switch on argument types
        if isinstance(args[0], Function):
            other = args[0]
            if len(args) == 1:
                # NOTE: Turn this into error when removing deprecation warning
                cpp.deprecation(
                    "Function copy constructor", "1.7.0", "2.0.0",
                    "Use 'Function.copy(deepcopy=True)' for copying.")
                self.__init_copy_constructor(other)
            elif len(args) == 2:
                i = args[1]
                if not isinstance(i, int):
                    raise TypeError("Invalid subfunction number %s" % (i, ))
                self.__init_subfunction_constructor(other, i)
            else:
                raise TypeError("expected one or two arguments when "
                                "instantiating from another Function")
        elif isinstance(args[0], cpp.Function):
            other = args[0]
            if len(args) == 1:
                # If creating a dolfin.Function from a cpp.Function
                self.__init_from_cpp_function(other)
            else:
                raise TypeError(
                    "expected only one argument when passing cpp.Function"
                    "to dolfin.Function constructor")
        elif isinstance(args[0], FunctionSpace):
            V = args[0]
            # If initialising from a FunctionSpace
            if len(args) == 1:
                # If passing only the FunctionSpace
                self.__init_from_function_space(V)
            elif len(args) == 2:
                # If passing FunctionSpace together with cpp.Function
                # Attached passed FunctionSpace and initialize the
                # cpp.Function using the passed Function
                other = args[1]
                if isinstance(other, cpp.Function):
                    self.__init_from_function_space_and_cpp_function(V, other)
                else:
                    self.__init_from_function_space_and_function(V, other)
            else:
                raise TypeError("too many arguments")
        else:
            raise TypeError(
                "expected a FunctionSpace or a Function as argument 1")

        # Set name as given or automatic
        name = kwargs.get("name") or "f_%d" % self.count()
        self.rename(name, "a Function")
Ejemplo n.º 6
0
    def __init__(self, *args, **kwargs):
        """Initialize Function."""
        # Initial quick check for valid arguments (other checks sprinkled below)
        if len(args) == 0:
            raise TypeError("expected 1 or more arguments")

        # Type switch on argument types
        if isinstance(args[0], Function):
            other = args[0]
            if len(args) == 1:
                # NOTE: Turn this into error when removing deprecation warning
                cpp.deprecation("Function copy constructor", "1.7.0", "2.0.0",
                                "Use 'Function.copy(deepcopy=True)' for copying.")
                self.__init_copy_constructor(other)
            elif len(args) == 2:
                i = args[1]
                if not isinstance(i, int):
                    raise TypeError("Invalid subfunction number %s" % (i,))
                self.__init_subfunction_constructor(other, i)
            else:
                raise TypeError("expected one or two arguments when "
                                "instantiating from another Function")
        elif isinstance(args[0], cpp.Function):
            other = args[0]
            if len(args) == 1:
                # If creating a dolfin.Function from a cpp.Function
                self.__init_from_cpp_function(other)
            else:
                raise TypeError("expected only one argument when passing cpp.Function"
                                "to dolfin.Function constructor")
        elif isinstance(args[0], FunctionSpace):
            V = args[0]
            # If initialising from a FunctionSpace
            if len(args) == 1:
                # If passing only the FunctionSpace
                self.__init_from_function_space(V)
            elif len(args) == 2:
                # If passing FunctionSpace together with cpp.Function
                # Attached passed FunctionSpace and initialize the
                # cpp.Function using the passed Function
                other = args[1]
                if isinstance(other, cpp.Function):
                    self.__init_from_function_space_and_cpp_function(V, other)
                else:
                    self.__init_from_function_space_and_function(V, other)
            else:
                raise TypeError("too many arguments")
        else:
            raise TypeError("expected a FunctionSpace or a Function as argument 1")

        # Set name as given or automatic
        name = kwargs.get("name") or "f_%d" % self.count()
        self.rename(name, "a Function")
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def compile_subdomains(cppcode):
    """
    Compile C++ string expressions into SubDomain instances. 

    *Arguments*
        expressions
            a string or a list of strings containing expressions in C++ syntax.

    NOTE: This function is deprecated. Use CompiledSubDomain instead.

    If expressions is a `str`, it is interpreted as a C++ string with
    complete implementations of subclasses of SubDomain. The compiled
    subdomains returned will be in the same order as they are defined
    in this code.
    
    If it is a list, each item of the list is interpreted as a logical
    `inside` expression, and the compiled subdomains returned will be
    in the same order as they occur in this list.
    
    If an expression string contains a name, it is assumed to be a
    scalar variable name, and is added as a public member of the
    generated subdomain.
    
    *Examples of usage*

        .. code-block:: python

            left  = compile_subdomains("x[0] == 0")
            right = compile_subdomains("x[1] == 1")

    or
    
        .. code-block:: python

            bc = compile_subdomains(["x[0] == 0", "x[1] == 1"])
    """
    
    deprecation("compile_subdomains", "1.3.0", \
                "compiled_subdomains has been renamed to CompiledSubDomain.")

    # If passing a list we compile each SubDomain on its own
    if isinstance(cppcode, list):
        return [CompiledSubDomain(code_str) for code_str in cppcode]

    return CompiledSubDomain(cppcode)
Ejemplo n.º 9
0
def compile_subdomains(cppcode):
    """
    Compile C++ string expressions into SubDomain instances. 

    *Arguments*
        expressions
            a string or a list of strings containing expressions in C++ syntax.

    NOTE: This function is deprecated. Use CompiledSubDomain instead.

    If expressions is a `str`, it is interpreted as a C++ string with
    complete implementations of subclasses of SubDomain. The compiled
    subdomains returned will be in the same order as they are defined
    in this code.
    
    If it is a list, each item of the list is interpreted as a logical
    `inside` expression, and the compiled subdomains returned will be
    in the same order as they occur in this list.
    
    If an expression string contains a name, it is assumed to be a
    scalar variable name, and is added as a public member of the
    generated subdomain.
    
    *Examples of usage*

        .. code-block:: python

            left  = compile_subdomains("x[0] == 0")
            right = compile_subdomains("x[1] == 1")

    or
    
        .. code-block:: python

            bc = compile_subdomains(["x[0] == 0", "x[1] == 1"])
    """
    
    deprecation("compile_subdomains", "1.3.0", \
                "compiled_subdomains has been renamed to CompiledSubDomain.")

    # If passing a list we compile each SubDomain on its own
    if isinstance(cppcode, list):
        return [CompiledSubDomain(code_str) for code_str in cppcode]

    return CompiledSubDomain(cppcode)
Ejemplo n.º 10
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
        form_arguments = form.arguments()

        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 new 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):
            cpp.deprecation(
                "derivative of form w.r.t. a tuple of Coefficients", "1.7.0",
                "2.0.0", "Take derivative w.r.t. a single Coefficient on "
                "a mixed space instead.")

            # Get mesh
            mesh = u[0].function_space().mesh()
            if not all(mesh.id() == v.function_space().mesh().id() for v in u):
                cpp.dolfin_error(
                    "formmanipulation.py", "compute derivative of form",
                    "Don't know how to compute derivative with "
                    "respect to Coefficients on different meshes yet")

            # Build mixed element, space and argument
            element = ufl.MixedElement(
                [v.function_space().ufl_element() for v in u])
            V = FunctionSpace(mesh, element)
            du = ufl.split(Argument(V, number, part))

        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form w.r.t. '%s'" % u,
                             "Supply Function as a Coefficient")

    return ufl.derivative(form, u, du, coefficient_derivatives)
Ejemplo n.º 11
0
def _plot_matplotlib(obj, mesh, kwargs):
    # Avoid importing until used
    import matplotlib.pyplot as plt

    gdim = mesh.geometry().dim()
    if gdim == 3 or kwargs.get("mode") in ("warp",):
        # Importing this toolkit has side effects enabling 3d support
        from mpl_toolkits.mplot3d import axes3d
        # Enabling the 3d toolbox requires some additional arguments
        ax = plt.gca(projection='3d')
    else:
        ax = plt.gca()
    ax.set_aspect('equal')

    title = kwargs.pop("title", None)
    if title is not None:
        ax.set_title(title)

    # Translate range_min/max kwargs supported by VTKPlotter
    vmin = kwargs.pop("range_min", None)
    vmax = kwargs.pop("range_max", None)
    if vmin and not "vmin" in kwargs:
        kwargs["vmin"] = vmin
    if vmax and not "vmax" in kwargs:
        kwargs["vmax"] = vmax

    # Let's stays consistent and use mode='color' instead of 'surface'
    if kwargs.get("mode") == "surface":
        cpp.deprecation("plot kwarg mode='surface'", "1.7.0", "1.7.0",
                        "Use mode='color' instead.")
        kwargs["mode"] = "color"

    if isinstance(obj, cpp.Function):
        return mplot_function(ax, obj, **kwargs)
    elif isinstance(obj, cpp.Expression):
        return mplot_expression(ax, obj, mesh, **kwargs)
    elif isinstance(obj, cpp.Mesh):
        return mplot_mesh(ax, obj, **kwargs)
    elif isinstance(obj, cpp.DirichletBC):
        return mplot_dirichletbc(ax, obj, **kwargs)
    elif isinstance(obj, _meshfunction_types):
        return mplot_meshfunction(ax, obj, **kwargs)
    else:
        raise AttributeError('Failed to plot %s' % type(obj))
Ejemplo n.º 12
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)
Ejemplo n.º 13
0
def _plot_matplotlib(obj, mesh, kwargs):
    # Avoid importing until used
    import matplotlib.pyplot as plt

    gdim = mesh.geometry().dim()
    if gdim == 3 or kwargs.get("mode") in ("warp", ):
        # Importing this toolkit has side effects enabling 3d support
        from mpl_toolkits.mplot3d import axes3d
        # Enabling the 3d toolbox requires some additional arguments
        ax = plt.gca(projection='3d')
    else:
        ax = plt.gca()
    ax.set_aspect('equal')

    title = kwargs.pop("title", None)
    if title is not None:
        ax.set_title(title)

    # Translate range_min/max kwargs supported by VTKPlotter
    vmin = kwargs.pop("range_min", None)
    vmax = kwargs.pop("range_max", None)
    if vmin and not "vmin" in kwargs:
        kwargs["vmin"] = vmin
    if vmax and not "vmax" in kwargs:
        kwargs["vmax"] = vmax

    # Let's stays consistent and use mode='color' instead of 'surface'
    if kwargs.get("mode") == "surface":
        cpp.deprecation("plot kwarg mode='surface'", "1.7.0", "1.7.0",
                        "Use mode='color' instead.")
        kwargs["mode"] = "color"

    if isinstance(obj, cpp.Function):
        return mplot_function(ax, obj, **kwargs)
    elif isinstance(obj, cpp.Expression):
        return mplot_expression(ax, obj, mesh, **kwargs)
    elif isinstance(obj, cpp.Mesh):
        return mplot_mesh(ax, obj, **kwargs)
    elif isinstance(obj, cpp.DirichletBC):
        return mplot_dirichletbc(ax, obj, **kwargs)
    elif isinstance(obj, _meshfunction_types):
        return mplot_meshfunction(ax, obj, **kwargs)
    else:
        raise AttributeError('Failed to plot %s' % type(obj))
Ejemplo n.º 14
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
        form_arguments = form.arguments()

        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 new 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):
            cpp.deprecation("derivative of form w.r.t. a tuple of Coefficients",
                            "1.7.0", "2.0.0",
                            "Take derivative w.r.t. a single Coefficient on "
                            "a mixed space instead.")

            # Get mesh
            mesh = u[0].function_space().mesh()
            if not all(mesh.id() == v.function_space().mesh().id() for v in u):
                cpp.dolfin_error("formmanipulation.py",
                                 "compute derivative of form",
                                 "Don't know how to compute derivative with "
                                 "respect to Coefficients on different meshes yet")

            # Build mixed element, space and argument
            element = ufl.MixedElement([v.function_space().ufl_element() for v in u])
            V = FunctionSpace(mesh, element)
            du = ufl.split(Argument(V, number, part))

        else:
            cpp.dolfin_error("formmanipulation.py",
                             "compute derivative of form w.r.t. '%s'" % u,
                             "Supply Function as a Coefficient")

    return ufl.derivative(form, u, du, coefficient_derivatives)
Ejemplo n.º 15
0
def homogenize(bc):
    """
    **DEPRECATED**:
    Return a homogeneous version of the given boundary condition.

    *Arguments*
        bc
            a :py:class:`DirichletBC <dolfin.fem.bcs.DirichletBC>` instance,
            or a list/tuple of
            :py:class:`DirichletBC <dolfin.fem.bcs.DirichletBC>` instances.

    Other types of boundary conditions are ignored.

    If the given boundary condition is a list of boundary conditions,
    then a list of homogeneous boundary conditions is returned.

    """
    # Deprecating it as it is very unclear what should it do
    # because DirichletBC employs some caching prepared on first use.
    # So if args of DirichetBC(*args) change it is not clear whether
    # whether cached dofs should be reused or thrown away on copy
    # cnstruction
    cpp.deprecation(
        "Free function 'homogenize(bc)'", "1.6.0", "1.7.0",
        "Use member function 'homogenize()' (in a combination"
        "with copy constructor 'DirichletBC(bc)'.")

    # Handle case when boundary condition is a list
    if isinstance(bc, (list, tuple)):
        bcs = bc
        return [homogenize(bc) for bc in bcs]

    # Only consider Dirichlet boundary conditions
    if not isinstance(bc, cpp.DirichletBC):
        cpp.dolfin_error("bcs.py", "homogenize boundary condition",
                         "Can only homogenize DirichletBCs")

    # Return homogenized copy
    new_bc = DirichletBC(bc)
    new_bc.homogenize()
    return new_bc
Ejemplo n.º 16
0
def homogenize(bc):
    """
    **DEPRECATED**:
    Return a homogeneous version of the given boundary condition.

    *Arguments*
        bc
            a :py:class:`DirichletBC <dolfin.fem.bcs.DirichletBC>` instance,
            or a list/tuple of
            :py:class:`DirichletBC <dolfin.fem.bcs.DirichletBC>` instances.

    Other types of boundary conditions are ignored.

    If the given boundary condition is a list of boundary conditions,
    then a list of homogeneous boundary conditions is returned.

    """
    # Deprecating it as it is very unclear what should it do
    # because DirichletBC employs some caching prepared on first use.
    # So if args of DirichetBC(*args) change it is not clear whether
    # whether cached dofs should be reused or thrown away on copy
    # cnstruction
    cpp.deprecation("Free function 'homogenize(bc)'", "1.6.0", "1.7.0",
                    "Use member function 'homogenize()' (in a combination"
                    "with copy constructor 'DirichletBC(bc)'.")

    # Handle case when boundary condition is a list
    if isinstance(bc, (list, tuple)):
        bcs = bc
        return [homogenize(bc) for bc in bcs]

    # Only consider Dirichlet boundary conditions
    if not isinstance(bc, cpp.DirichletBC):
        cpp.dolfin_error("bcs.py",
                         "homogenize boundary condition",
                         "Can only homogenize DirichletBCs")

    # Return homogenized copy
    new_bc = DirichletBC(bc)
    new_bc.homogenize()
    return new_bc
Ejemplo n.º 17
0
def FunctionSpaceFromCpp(cppV):
    cpp.deprecation("'FunctionSpaceFromCpp'", "1.7.0", "2.0.0",
                    "Use 'FunctionSpace(cppV)' instead.")
    return FunctionSpace(cppV)
Ejemplo n.º 18
0
 def cell(self):
     "Return the UFL cell."
     cpp.deprecation("'FunctionSpace.cell()'", "1.7.0", "2.0.0",
                     "Use 'FunctionSpace.ufl_cell()' instead.")
     return self.ufl_cell()
Ejemplo n.º 19
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)
Ejemplo n.º 20
0
def _mesh2domain(mesh):
    "Deprecation mechanism for symbolic geometry."
    if isinstance(mesh, ufl.Cell):
        cpp.deprecation("Constructing geometry from a Cell", "1.4", "1.5",
                    "Pass mesh instead, for example use FacetNormal(mesh) instead of FacetNormal(triangle) or triangle.n")
    return ufl.as_domain(mesh)
Ejemplo n.º 21
0
def assemble(form,
             tensor=None,
             mesh=None,
             coefficients=None,
             function_spaces=None,
             cell_domains=None,
             exterior_facet_domains=None,
             interior_facet_domains=None,
             reset_sparsity=True,
             add_values=False,
             finalize_tensor=True,
             keep_diagonal=False,
             backend=None,
             form_compiler_parameters=None,
             bcs=None):
    """
    Assemble the given form and return the corresponding tensor.

    *Arguments*
        Depending on the input form, which may be a functional, linear
        form, bilinear form or higher rank form, a scalar value, a vector,
        a matrix or a higher rank tensor is returned.

    In the simplest case, no additional arguments are needed. However,
    additional arguments may and must in some cases be provided as
    outlined below.

    The ``form`` can be either an FFC form or a precompiled UFC
    form. If a precompiled or 'pure' UFC form is given, then
    ``coefficients`` and ``function_spaces`` have to be provided
    too. The coefficient functions should be provided as a 'dict'
    using the FFC functions as keys. The function spaces should be
    provided either as a list where the number of function spaces must
    correspond to the number of basis functions in the form, or as a
    single argument, implying that the same FunctionSpace is used for
    all test/trial spaces.

    If the form defines integrals over different subdomains,
    :py:class:`MeshFunctions <dolfin.cpp.MeshFunction>` over the
    corresponding topological entities defining the subdomains can be
    provided. An instance of a :py:class:`SubDomain
    <dolfin.cpp.SubDomain>` can also be passed for each subdomain.

    The implementation of the returned tensor is determined by the
    default linear algebra backend. This can be overridden by
    specifying a different backend.

    Each call to assemble() will create a new tensor. If the
    ``tensor`` argument is provided, this will be used instead. If
    ``reset_sparsity`` is set to False, the provided tensor will not be
    reset to zero before assembling (adding) values to the tensor.

    If the ``keep_diagonal`` is set to True, assembler ensures that
    potential zeros on a matrix diagonal are kept in sparsity pattern
    so every diagonal entry can be changed in a future (for example
    by ident() or ident_zeros()).

    Specific form compiler parameters can be provided by the
    ``form_compiler_parameters`` argument. Form compiler parameters
    can also be controlled using the global parameters stored in
    parameters["form_compiler"].

    *Examples of usage*
        The standard stiffness matrix ``A`` and a load vector ``b``
        can be assembled as follows:

        .. code-block:: python

            A = assemble(inner(grad(u),grad(v))*dx())
            b = assemble(f*v*dx())

        It is possible to explicitly prescribe the domains over which
        integrals wll be evaluated using the arguments
        ``cell_domains``, ``exterior_facet_domains`` and
        ``interior_facet_domains``. For instance, using a mesh
        function marking parts of the boundary:

        .. code-block:: python

            # MeshFunction marking boundary parts
            boundary_parts = MeshFunction("size_t", mesh, mesh.topology().dim()-1)

            # Sample variational forms
            a = inner(grad(u), grad(v))*dx() + p*u*v*ds(0)
            L = f*v*dx() - g*v*ds(1) + p*q*v*ds(0)

            A = assemble(a, exterior_facet_domains=boundary_parts)
            b = assemble(L, exterior_facet_domains=boundary_parts)

        To ensure that the assembled matrix has the right type, one may use
        the ``tensor`` argument:

        .. code-block:: python

            A = PETScMatrix()
            assemble(a, tensor=A)

        The form ``a`` is now assembled into the PETScMatrix ``A``.

    """
    # Create dolfin Form object referencing all data needed by assembler
    dolfin_form = _create_dolfin_form(form, mesh, coefficients, function_spaces,
                                      cell_domains, exterior_facet_domains, interior_facet_domains, form_compiler_parameters)

    # Create tensor
    tensor = _create_tensor(form, dolfin_form.rank(), backend, tensor)

    # Call C++ assemble function
    assembler = cpp.Assembler()
    assembler.reset_sparsity = reset_sparsity
    assembler.add_values = add_values
    assembler.finalize_tensor = finalize_tensor
    assembler.keep_diagonal = keep_diagonal
    assembler.assemble(tensor, dolfin_form)

    # Convert to float for scalars
    if dolfin_form.rank() == 0:
        tensor = tensor.getval()

    # Apply (possibly list of) boundary conditions
    bcs = _wrap_in_list(bcs, 'bcs', cpp.DirichletBC)
    if bcs:
        cpp.deprecation("Passing \"bcs\" to assemble", "1.3.0",
                        "Apply DirichletBC manually after an assemble.")
    for bc in bcs:
        bc.apply(tensor)

    # Return value
    return tensor
Ejemplo n.º 22
0
def FunctionSpaceFromCpp(cppV):
    cpp.deprecation("'FunctionSpaceFromCpp'", "1.7.0", "2.0.0",
                    "Use 'FunctionSpace(cppV)' instead.")
    return FunctionSpace(cppV)
Ejemplo n.º 23
0
 def _sub(self, i, deepcopy = False):
     cpp.deprecation("Using Function._sub", "1.3.0",
                     "Use Function.sub instead")
     self.sub(i, deepcopy)
Ejemplo n.º 24
0
 def _sub(self, i, deepcopy=False):
     cpp.deprecation("Using Function._sub", "1.3.0",
                     "Use Function.sub instead")
     self.sub(i, deepcopy)
Ejemplo n.º 25
0
 def cell(self):
     "Return the UFL cell."
     cpp.deprecation("'FunctionSpace.cell()'", "1.7.0", "2.0.0",
                     "Use 'FunctionSpace.ufl_cell()' instead.")
     return self.ufl_cell()
Ejemplo n.º 26
0
def assemble_system(A_form,
                    b_form,
                    bcs=None,
                    x0=None,
                    A_coefficients=None,
                    b_coefficients=None,
                    A_function_spaces=None,
                    b_function_spaces=None,
                    cell_domains=None,
                    exterior_facet_domains=None,
                    interior_facet_domains=None,
                    reset_sparsity=None,
                    add_values=False,
                    finalize_tensor=True,
                    keep_diagonal=False,
                    A_tensor=None,
                    b_tensor=None,
                    mesh=None,
                    backend=None,
                    form_compiler_parameters=None):
    """
    Assemble form(s) and apply any given boundary conditions in a
    symmetric fashion and return tensor(s).

    The standard application of boundary conditions does not
    necessarily preserve the symmetry of the assembled matrix. In
    order to perserve symmetry in a system of equations with boundary
    conditions, one may use the alternative assemble_system instead of
    multiple calls to :py:func:`assemble
    <dolfin.fem.assembling.assemble>`.

    *Examples of usage*

       For instance, the statements

       .. code-block:: python

           A = assemble(a)
           b = assemble(L)
           bc.apply(A, b)

       can alternatively be carried out by

       .. code-block:: python

           A, b = assemble_system(a, L, bc)

       The statement above is valid even if ``bc`` is a list of
       :py:class:`DirichletBC <dolfin.fem.bcs.DirichletBC>`
       instances. For more info and options, see :py:func:`assemble
       <dolfin.fem.assembling.assemble>`.

    """
    if reset_sparsity is not None:
        cpp.deprecation("Parameter reset_sparsity of assembler",
                        "1.4", "1.5",
                        "Parameter reset_sparsity of assembler"
                        " is no longer used. Tensor is reset iff empty().")

    # Create dolfin Form objects referencing all data needed by assembler
    A_dolfin_form = _create_dolfin_form(A_form, mesh, A_coefficients, A_function_spaces,
                                        cell_domains, exterior_facet_domains, interior_facet_domains, form_compiler_parameters)
    b_dolfin_form = _create_dolfin_form(b_form, mesh, b_coefficients, b_function_spaces,
                                        cell_domains, exterior_facet_domains, interior_facet_domains, form_compiler_parameters)

    # Create tensors
    A_tensor = _create_tensor(A_form, A_dolfin_form.rank(), backend, A_tensor)
    b_tensor = _create_tensor(b_form, b_dolfin_form.rank(), backend, b_tensor)

    # Check bcs
    bcs = _wrap_in_list(bcs, 'bcs', cpp.DirichletBC)

    # Call C++ assemble function
    assembler = cpp.SystemAssembler(A_dolfin_form, b_dolfin_form, bcs)
    assembler.add_values = add_values
    assembler.finalize_tensor = finalize_tensor
    assembler.keep_diagonal = keep_diagonal
    if x0 is not None:
        assembler.assemble(A_tensor, b_tensor, x0)
    else:
        assembler.assemble(A_tensor, b_tensor)

    return A_tensor, b_tensor
Ejemplo n.º 27
0
def FunctionSpaceBase(mesh, element, constrained_domain=None):
    cpp.deprecation("'FunctionSpaceBase'", "1.7.0", "2.0.0",
                    "Use 'FunctionSpace(...)' instead.")
    return FunctionSpace(mesh, element, constrained_domain=None)
Ejemplo n.º 28
0
def assemble(form,
             tensor=None,
             mesh=None,
             coefficients=None,
             function_spaces=None,
             cell_domains=None,
             exterior_facet_domains=None,
             interior_facet_domains=None,
             reset_sparsity=True,
             add_values=False,
             finalize_tensor=True,
             keep_diagonal=False,
             backend=None,
             form_compiler_parameters=None,
             bcs=None):
    """
    Assemble the given form and return the corresponding tensor.

    *Arguments*
        Depending on the input form, which may be a functional, linear
        form, bilinear form or higher rank form, a scalar value, a vector,
        a matrix or a higher rank tensor is returned.

    In the simplest case, no additional arguments are needed. However,
    additional arguments may and must in some cases be provided as
    outlined below.

    The ``form`` can be either an FFC form or a precompiled UFC
    form. If a precompiled or 'pure' UFC form is given, then
    ``coefficients`` and ``function_spaces`` have to be provided
    too. The coefficient functions should be provided as a 'dict'
    using the FFC functions as keys. The function spaces should be
    provided either as a list where the number of function spaces must
    correspond to the number of basis functions in the form, or as a
    single argument, implying that the same FunctionSpace is used for
    all test/trial spaces.

    If the form defines integrals over different subdomains,
    :py:class:`MeshFunctions <dolfin.cpp.MeshFunction>` over the
    corresponding topological entities defining the subdomains can be
    provided. An instance of a :py:class:`SubDomain
    <dolfin.cpp.SubDomain>` can also be passed for each subdomain.

    The implementation of the returned tensor is determined by the
    default linear algebra backend. This can be overridden by
    specifying a different backend.

    Each call to assemble() will create a new tensor. If the
    ``tensor`` argument is provided, this will be used instead. If
    ``reset_sparsity`` is set to False, the provided tensor will not be
    reset to zero before assembling (adding) values to the tensor.

    If the ``keep_diagonal`` is set to True, assembler ensures that
    potential zeros on a matrix diagonal are kept in sparsity pattern
    so every diagonal entry can be changed in a future (for example
    by ident() or ident_zeros()).

    Specific form compiler parameters can be provided by the
    ``form_compiler_parameters`` argument. Form compiler parameters
    can also be controlled using the global parameters stored in
    parameters["form_compiler"].

    *Examples of usage*
        The standard stiffness matrix ``A`` and a load vector ``b``
        can be assembled as follows:

        .. code-block:: python

            A = assemble(inner(grad(u),grad(v))*dx())
            b = assemble(f*v*dx())

        It is possible to explicitly prescribe the domains over which
        integrals wll be evaluated using the arguments
        ``cell_domains``, ``exterior_facet_domains`` and
        ``interior_facet_domains``. For instance, using a mesh
        function marking parts of the boundary:

        .. code-block:: python

            # MeshFunction marking boundary parts
            boundary_parts = MeshFunction("size_t", mesh, mesh.topology().dim()-1)

            # Sample variational forms
            a = inner(grad(u), grad(v))*dx() + p*u*v*ds(0)
            L = f*v*dx() - g*v*ds(1) + p*q*v*ds(0)

            A = assemble(a, exterior_facet_domains=boundary_parts)
            b = assemble(L, exterior_facet_domains=boundary_parts)

        To ensure that the assembled matrix has the right type, one may use
        the ``tensor`` argument:

        .. code-block:: python

            A = PETScMatrix()
            assemble(a, tensor=A)

        The form ``a`` is now assembled into the PETScMatrix ``A``.

    """

    # Extract common cell from mesh (may be missing in form definition)
    common_cell = None if mesh is None else mesh.ufl_cell()

    # First check if we got a cpp.Form which originates from cpp layer
    if isinstance(form, cpp.Form) and not hasattr(form, "_compiled_form"):

        # Then we just try to use that one
        dolfin_form = form

    else:

        # Wrap form
        dolfin_form = Form(form,
                           function_spaces=function_spaces,
                           coefficients=coefficients,
                           form_compiler_parameters=form_compiler_parameters,
                           common_cell=common_cell)

    # Set mesh if specified (important for functionals without a function spaces)
    if mesh is not None:
        dolfin_form.set_mesh(mesh)

    # Create tensor
    tensor = _create_tensor(form, dolfin_form.rank(), backend, tensor)

    # Extract domains
    cell_domains, exterior_facet_domains, interior_facet_domains = \
        _extract_domains(dolfin_form.mesh(),
                         cell_domains,
                         exterior_facet_domains,
                         interior_facet_domains)

    # Attach domains to form
    if cell_domains is not None:
        dolfin_form.set_cell_domains(cell_domains)
    if interior_facet_domains is not None:
        dolfin_form.set_interior_facet_domains(interior_facet_domains)
    if exterior_facet_domains is not None:
        dolfin_form.set_exterior_facet_domains(exterior_facet_domains)

    # Call C++ assemble function
    assembler = cpp.Assembler()
    assembler.reset_sparsity = reset_sparsity
    assembler.add_values = add_values
    assembler.finalize_tensor = finalize_tensor
    assembler.keep_diagonal = keep_diagonal
    assembler.assemble(tensor, dolfin_form)

    # Convert to float for scalars
    if dolfin_form.rank() == 0:
        tensor = tensor.getval()

    # Apply (possibly list of) boundary conditions
    bcs = _wrap_in_list(bcs, 'bcs', cpp.DirichletBC)
    if bcs:
        cpp.deprecation("Passing \"bcs\" to assemble", "1.3.0",
                        "Apply DirichletBC manually after an assemble.")
    for bc in bcs:
        bc.apply(tensor)

    # Return value
    return tensor
Ejemplo n.º 29
0
def FunctionSpaceBase(mesh, element, constrained_domain=None):
    cpp.deprecation("'FunctionSpaceBase'", "1.7.0", "2.0.0",
                    "Use 'FunctionSpace(...)' instead.")
    return FunctionSpace(mesh, element, constrained_domain=None)