# -*- coding: utf-8 -*-
"This module provides uniform and local mesh refinement."

# Copyright (C) 2009 Anders Logg
#
# This file is part of DOLFIN.
#
# DOLFIN is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DOLFIN is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2010-02-26
# Last changed: 2010-02-26

__all__ = ["refine"]

# Import C++ interface
import dolfin.cpp as cpp

def refine(mesh, cell_markers=None, redistribute=True):
    """
    Refine given mesh and return the refined mesh.

    *Arguments*
        mesh
            the :py:class:`Mesh <dolfin.cpp.Mesh>` to be refined.
        cell_markers
            an optional argument (a boolean :py:class:`MeshFunction
            <dolfin.cpp.MeshFunctionBool>` over cells) may be given
            to specify which cells should be refined. If no cell
            markers are given, then the mesh is refined uniformly.
        redistribute
            an optional argument (boolean) may be given to set whether
            to redistribute the mesh across processes following
            refinement. The is relevant only when the mesh is
            distributed across processes. In serial the argument has
            no impact. Default it True.

    *Examples of usage*

        .. code-block:: python

            mesh = refine(mesh)

        To only refine cells with too large error, define a boolean
        MeshFunction over the mesh and mark the cells to be refined
        as True.

        .. code-block:: python

            cell_markers = CellFunction("bool", mesh)
            cell_markers.set_all(False)
            for cell in cells(mesh):
                # set cell_markers[cell] = True if the cell's error
                # indicator is greater than some criterion.
            mesh = refine(mesh, cell_markers)

    """

    # This function is necessary to avoid copying in the wrapped
    # versions of the return-by-value refine functions in C++.

    # Create empty mesh
    refined_mesh = cpp.Mesh(mesh.mpi_comm())

    # Call C++ refinement
    if cell_markers is None:
        cpp.refine(refined_mesh, mesh, redistribute)
    else:
        cpp.refine(refined_mesh, mesh, cell_markers, redistribute)

    return refined_mesh
