Пример #1
0
    def initialize(self, obj):
        if complex_mode:
            raise NotImplementedError("HypreAMS preconditioner not yet implemented in complex mode")

        Citations().register("Kolev2009")
        A, P = obj.getOperators()
        prefix = obj.getOptionsPrefix()
        V = get_function_space(obj.getDM())
        mesh = V.mesh()

        family = str(V.ufl_element().family())
        degree = V.ufl_element().degree()
        if family != 'Nedelec 1st kind H(curl)' or degree != 1:
            raise ValueError("Hypre AMS requires lowest order Nedelec elements! (not %s of degree %d)" % (family, degree))

        P1 = FunctionSpace(mesh, "Lagrange", 1)
        G = Interpolator(grad(TestFunction(P1)), V).callable().handle

        pc = PETSc.PC().create(comm=obj.comm)
        pc.incrementTabLevel(1, parent=obj)
        pc.setOptionsPrefix(prefix + "hypre_ams_")
        pc.setOperators(A, P)

        pc.setType('hypre')
        pc.setHYPREType('ams')
        pc.setHYPREDiscreteGradient(G)
        zero_beta = PETSc.Options(prefix).getBool("pc_hypre_ams_zero_beta_poisson", default=False)
        if zero_beta:
            pc.setHYPRESetBetaPoissonMatrix(None)

        VectorP1 = VectorFunctionSpace(mesh, "Lagrange", 1)
        pc.setCoordinates(interpolate(SpatialCoordinate(mesh), VectorP1).dat.data_ro.copy())
        pc.setUp()

        self.pc = pc
Пример #2
0
def pick_mode(mode):
    "Return one of the specialized optimisation modules from a mode string."
    try:
        from firedrake_citations import Citations
        cites = {
            "vanilla": ("Homolya2017", ),
            "coffee": (
                "Luporini2016",
                "Homolya2017",
            ),
            "spectral": ("Luporini2016", "Homolya2017", "Homolya2017a"),
            "tensor": (
                "Kirby2006",
                "Homolya2017",
            )
        }
        for c in cites[mode]:
            Citations().register(c)
    except ImportError:
        pass
    if mode == "vanilla":
        import tsfc.vanilla as m
    elif mode == "coffee":
        import tsfc.coffee_mode as m
    elif mode == "spectral":
        import tsfc.spectral as m
    elif mode == "tensor":
        import tsfc.tensor as m
    else:
        raise ValueError("Unknown mode: {}".format(mode))
    return m
Пример #3
0
def update_citations(params):
    """Update citations list for known COFFEE users."""

    # Firedrake
    try:
        from firedrake_citations import Citations
        rewrite = params.get('rewrite', 0)
        nozeros = params.get('dead_ops_elimination', False)
        align_pad = params.get('align_pad', False)
        vectorize = params.get('vectorize', False)
        split = params.get('split', False)

        if rewrite == 1 or align_pad or vectorize or split:
            Citations().register('Luporini2015')
        if rewrite > 1 or nozeros:
            Citations().register('Luporini2016')
    except ImportError:
        pass
Пример #4
0
 def __init__(self, meshes, coarse_to_fine_cells, fine_to_coarse_cells):
     from firedrake_citations import Citations
     Citations().register("Mitchell2016")
     self.meshes = tuple(meshes)
     self.coarse_to_fine_cells = tuple(coarse_to_fine_cells)
     self.fine_to_coarse_cells = tuple(fine_to_coarse_cells)
     for level, m in enumerate(self):
         set_level(m, self, level)
     self._shared_data_cache = defaultdict(dict)
Пример #5
0
def generate_loopy_kernel(slate_expr, tsfc_parameters=None):
    cpu_time = time.time()
    if len(slate_expr.ufl_domains()) > 1:
        raise NotImplementedError("Multiple domains not implemented.")

    Citations().register("Gibson2018")

    # Create a loopy builder for the Slate expression,
    # e.g. contains the loopy kernels coming from TSFC
    gem_expr, var2terminal = slate_to_gem(slate_expr)

    scalar_type = tsfc_parameters["scalar_type"]
    slate_loopy, output_arg = gem_to_loopy(gem_expr, var2terminal, scalar_type)

    builder = LocalLoopyKernelBuilder(expression=slate_expr,
                                      tsfc_parameters=tsfc_parameters)

    loopy_merged = merge_loopy(slate_loopy, output_arg, builder, var2terminal)
    loopy_merged = loopy.register_function_id_to_in_knl_callable_mapper(
        loopy_merged, inv_fn_lookup)
    loopy_merged = loopy.register_function_id_to_in_knl_callable_mapper(
        loopy_merged, solve_fn_lookup)

    # WORKAROUND: Generate code directly from the loopy kernel here,
    # then attach code as a c-string to the op2kernel
    code = loopy.generate_code_v2(loopy_merged).device_code()
    code = code.replace(f'void {loopy_merged.name}',
                        f'static void {loopy_merged.name}')
    loopykernel = op2.Kernel(code,
                             loopy_merged.name,
                             include_dirs=BLASLAPACK_INCLUDE.split(),
                             ldargs=BLASLAPACK_LIB.split())

    kinfo = KernelInfo(
        kernel=loopykernel,
        integral_type=
        "cell",  # slate can only do things as contributions to the cell integrals
        oriented=builder.bag.needs_cell_orientations,
        subdomain_id="otherwise",
        domain_number=0,
        coefficient_map=tuple(range(len(slate_expr.coefficients()))),
        needs_cell_facets=builder.bag.needs_cell_facets,
        pass_layer_arg=builder.bag.needs_mesh_layers,
        needs_cell_sizes=builder.bag.needs_cell_sizes)

    # Cache the resulting kernel
    # Slate kernels are never split, so indicate that with None in the index slot.
    idx = tuple([None] * slate_expr.rank)
    logger.info(GREEN % "compile_slate_expression finished in %g seconds.",
                time.time() - cpu_time)
    return (SplitKernel(idx, kinfo), )
Пример #6
0
 def __init__(self, meshes, coarse_to_fine_cells, fine_to_coarse_cells,
              refinements_per_level=1):
     from firedrake_citations import Citations
     Citations().register("Mitchell2016")
     self._meshes = tuple(meshes)
     self.meshes = tuple(meshes[::refinements_per_level])
     self.coarse_to_fine_cells = coarse_to_fine_cells
     self.fine_to_coarse_cells = fine_to_coarse_cells
     self.refinements_per_level = refinements_per_level
     for level, m in enumerate(meshes):
         set_level(m, self, Fraction(level, refinements_per_level))
     for level, m in enumerate(self):
         set_level(m, self, level)
     self._shared_data_cache = defaultdict(dict)
Пример #7
0
    def __init__(self):
        """Create a PC context suitable for PETSc.

        Matrix free preconditioners should inherit from this class and
        implement:

        - :meth:`initialize`
        - :meth:`update`
        - :meth:`apply`
        - :meth:`applyTranspose`

        """
        Citations().register("Kirby2017")
        self.initialized = False
        super(PCBase, self).__init__()
Пример #8
0
def generate_loopy_kernel(slate_expr, tsfc_parameters=None):
    cpu_time = time.time()
    if len(slate_expr.ufl_domains()) > 1:
        raise NotImplementedError("Multiple domains not implemented.")

    Citations().register("Gibson2018")

    # Create a loopy builder for the Slate expression,
    # e.g. contains the loopy kernels coming from TSFC
    gem_expr, var2terminal = slate_to_gem(slate_expr)

    scalar_type = tsfc_parameters["scalar_type"]
    slate_loopy, output_arg = gem_to_loopy(gem_expr, var2terminal, scalar_type)

    builder = LocalLoopyKernelBuilder(expression=slate_expr,
                                      tsfc_parameters=tsfc_parameters)

    name = "slate_wrapper"
    loopy_merged = merge_loopy(slate_loopy, output_arg, builder, var2terminal,
                               name)
    loopy_merged = loopy.register_callable(loopy_merged, INVCallable.name,
                                           INVCallable())
    loopy_merged = loopy.register_callable(loopy_merged, SolveCallable.name,
                                           SolveCallable())

    loopykernel = op2.Kernel(loopy_merged,
                             name,
                             include_dirs=BLASLAPACK_INCLUDE.split(),
                             ldargs=BLASLAPACK_LIB.split())

    kinfo = KernelInfo(
        kernel=loopykernel,
        integral_type=
        "cell",  # slate can only do things as contributions to the cell integrals
        oriented=builder.bag.needs_cell_orientations,
        subdomain_id="otherwise",
        domain_number=0,
        coefficient_map=tuple(range(len(slate_expr.coefficients()))),
        needs_cell_facets=builder.bag.needs_cell_facets,
        pass_layer_arg=builder.bag.needs_mesh_layers,
        needs_cell_sizes=builder.bag.needs_cell_sizes)

    # Cache the resulting kernel
    # Slate kernels are never split, so indicate that with None in the index slot.
    idx = tuple([None] * slate_expr.rank)
    logger.info(GREEN % "compile_slate_expression finished in %g seconds.",
                time.time() - cpu_time)
    return (SplitKernel(idx, kinfo), )
Пример #9
0
    def initialize(self, obj):
        if complex_mode:
            raise NotImplementedError(
                "HypreAMS preconditioner not yet implemented in complex mode")

        Citations().register("Kolev2009")
        A, P = obj.getOperators()
        prefix = obj.getOptionsPrefix()
        V = get_function_space(obj.getDM())
        mesh = V.mesh()

        family = str(V.ufl_element().family())
        degree = V.ufl_element().degree()
        if family != 'Nedelec 1st kind H(curl)' or degree != 1:
            raise ValueError(
                "Hypre AMS requires lowest order Nedelec elements! (not %s of degree %d)"
                % (family, degree))

        P1 = FunctionSpace(mesh, "Lagrange", 1)
        G = Interpolator(grad(TestFunction(P1)), V).callable().handle

        pc = PETSc.PC().create(comm=obj.comm)
        pc.incrementTabLevel(1, parent=obj)
        pc.setOptionsPrefix(prefix + "hypre_ams_")
        pc.setOperators(A, P)

        pc.setType('hypre')
        pc.setHYPREType('ams')
        pc.setHYPREDiscreteGradient(G)
        zero_beta = PETSc.Options(prefix).getBool(
            "pc_hypre_ams_zero_beta_poisson", default=False)
        if zero_beta:
            pc.setHYPRESetBetaPoissonMatrix(None)

        # Build constants basis for the Nedelec space
        cvecs = []
        for i in range(mesh.cell_dimension()):
            direction = [
                1.0 if i == j else 0.0 for j in range(mesh.cell_dimension())
            ]
            c = project(Constant(direction), V)
            with c.vector().dat.vec_ro as cvec:
                cvecs.append(cvec)
        pc.setHYPRESetEdgeConstantVectors(*cvecs)
        pc.setUp()

        self.pc = pc
Пример #10
0
def generate_kernel(slate_expr, tsfc_parameters=None):
    cpu_time = time.time()
    # TODO: Get PyOP2 to write into mixed dats
    if slate_expr.is_mixed:
        raise NotImplementedError("Compiling mixed slate expressions")

    if len(slate_expr.ufl_domains()) > 1:
        raise NotImplementedError("Multiple domains not implemented.")

    Citations().register("Gibson2018")
    # Create a builder for the Slate expression
    builder = LocalKernelBuilder(expression=slate_expr,
                                 tsfc_parameters=tsfc_parameters)

    # Keep track of declared temporaries
    declared_temps = {}
    statements = []

    # Declare terminal tensor temporaries
    terminal_declarations = terminal_temporaries(builder, declared_temps)
    statements.extend(terminal_declarations)

    # Generate assembly calls for tensor assembly
    subkernel_calls = tensor_assembly_calls(builder)
    statements.extend(subkernel_calls)

    # Create coefficient temporaries if necessary
    if builder.coefficient_vecs:
        coefficient_temps = coefficient_temporaries(builder, declared_temps)
        statements.extend(coefficient_temps)

    # Create auxiliary temporaries/expressions (if necessary)
    statements.extend(auxiliary_expressions(builder, declared_temps))

    # Generate the kernel information with complete AST
    kinfo = generate_kernel_ast(builder, statements, declared_temps)

    # Cache the resulting kernel
    idx = tuple([0] * slate_expr.rank)
    logger.info(GREEN % "compile_slate_expression finished in %g seconds.",
                time.time() - cpu_time)
    return (SplitKernel(idx, kinfo), )
Пример #11
0
import gem
from gem.utils import cached_property

from finat.finiteelementbase import FiniteElementBase
from finat.point_set import PointSet
from finat.sympy2gem import sympy2gem

try:
    from firedrake_citations import Citations
    Citations().add(
        "Geevers2018new", """
@article{Geevers2018new,
 title={New higher-order mass-lumped tetrahedral elements for wave propagation modelling},
 author={Geevers, Sjoerd and Mulder, Wim A and van der Vegt, Jaap JW},
 journal={SIAM journal on scientific computing},
 volume={40},
 number={5},
 pages={A2830--A2857},
 year={2018},
 publisher={SIAM},
 doi={https://doi.org/10.1137/18M1175549},
}
""")
    Citations().add(
        "Chin1999higher", """
@article{chin1999higher,
 title={Higher-order triangular and tetrahedral finite elements with mass lumping for solving the wave equation},
 author={Chin-Joe-Kong, MJS and Mulder, Wim A and Van Veldhuizen, M},
 journal={Journal of Engineering Mathematics},
 volume={35},
 number={4},
 pages={405--426},
Пример #12
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     if Citations is not None:
         Citations().register("Kirby2018zany")
         Citations().register("Kirby2019zany")
Пример #13
0
import gem
from abc import ABCMeta, abstractmethod

try:
    from firedrake_citations import Citations
    Citations().add(
        "Kirby2018zany", """
@Article{Kirby2018zany,
  author =       {Robert C. Kirby},
  title =        {A general approach to transforming finite elements},
  journal =      {SMAI Journal of Computational Mathematics},
  year =         2018,
  volume =       4,
  pages =        {197-224},
  doi =          {10.5802/smai-jcm.33},
  archiveprefix ={arXiv},
  eprint =       {1706.09017},
  primaryclass = {math.NA}
}
""")
    Citations().add(
        "Kirby2019zany", """
@Article{Kirby:2019,
  author =       {Robert C. Kirby and Lawrence Mitchell},
  title =        {Code generation for generally mapped finite
                  elements},
  journal =      {ACM Transactions on Mathematical Software},
  year =         2019,
  volume =       45,
  number =       41,
  pages =        {41:1--41:23},
Пример #14
0
#
# To get around this, since the default __del__ on Expr is just
# "pass", we just remove the method from the definition of Expr.
import ufl
try:
    del ufl.core.expr.Expr.__del__
except AttributeError:
    pass
del ufl
from ufl import *
# Set up the cache directories before importing PyOP2.
firedrake_configuration.setup_cache_dirs()

from firedrake_citations import Citations  # noqa: F401
# Always get the firedrake paper.
Citations().register("Rathgeber2016")
from pyop2 import op2  # noqa: F401
from pyop2.mpi import COMM_WORLD, COMM_SELF  # noqa: F401

from firedrake.assemble import *
from firedrake.bcs import *
from firedrake.checkpointing import *
from firedrake.constant import *
from firedrake.exceptions import *
from firedrake.expression import *
from firedrake.function import *
from firedrake.functionspace import *
from firedrake.interpolation import *
from firedrake.output import *
from firedrake.linear_solver import *
from firedrake.matrix_free.preconditioners import *
Пример #15
0
 def __init__(self, cell, degree):
     super(KongMulderVeldhuizen,
           self).__init__(FIAT.KongMulderVeldhuizen(cell, degree))
     if Citations is not None:
         Citations().register("Chin1999higher")
         Citations().register("Geevers2018new")
Пример #16
0
def compile_expression(slate_expr, tsfc_parameters=None):
    """Takes a Slate expression `slate_expr` and returns the appropriate
    :class:`firedrake.op2.Kernel` object representing the Slate expression.

    :arg slate_expr: a :class:'TensorBase' expression.
    :arg tsfc_parameters: an optional `dict` of form compiler parameters to
        be passed to TSFC during the compilation of ufl forms.

    Returns: A `tuple` containing a `SplitKernel(idx, kinfo)`
    """

    if not isinstance(slate_expr, slate.TensorBase):
        raise ValueError("Expecting a `TensorBase` object, not %s" %
                         type(slate_expr))

    # If the expression has already been symbolically compiled, then
    # simply reuse the produced kernel.
    if slate_expr._metakernel_cache is not None:
        return slate_expr._metakernel_cache

    # TODO: Get PyOP2 to write into mixed dats
    if slate_expr.is_mixed:
        raise NotImplementedError("Compiling mixed slate expressions")

    if len(slate_expr.ufl_domains()) > 1:
        raise NotImplementedError("Multiple domains not implemented.")

    Citations().register("Gibson2018")
    # Create a builder for the Slate expression
    builder = LocalKernelBuilder(expression=slate_expr,
                                 tsfc_parameters=tsfc_parameters)

    # Keep track of declared temporaries
    declared_temps = {}
    statements = []

    # Declare terminal tensor temporaries
    terminal_declarations = terminal_temporaries(builder, declared_temps)
    statements.extend(terminal_declarations)

    # Generate assembly calls for tensor assembly
    subkernel_calls = tensor_assembly_calls(builder)
    statements.extend(subkernel_calls)

    # Create coefficient temporaries if necessary
    if builder.coefficient_vecs:
        coefficient_temps = coefficient_temporaries(builder, declared_temps)
        statements.extend(coefficient_temps)

    # Create auxiliary temporaries/expressions (if necessary)
    statements.extend(auxiliary_expressions(builder, declared_temps))

    # Generate the kernel information with complete AST
    kinfo = generate_kernel_ast(builder, statements, declared_temps)

    # Cache the resulting kernel
    idx = tuple([0] * slate_expr.rank)
    kernel = (SplitKernel(idx, kinfo), )
    slate_expr._metakernel_cache = kernel

    return kernel
Пример #17
0
from tsfc.driver import compile_form, compile_expression_at_points  # noqa: F401
from tsfc.parameters import default_parameters  # noqa: F401

try:
    from firedrake_citations import Citations
    Citations().add("Kirby2006", """
@Article{Kirby2006,
  author =       {Kirby, Robert C. and Logg, Anders},
  title =        {A Compiler for Variational Forms},
  journal =      {ACM Trans. Math. Softw.},
  year =         2006,
  volume =       32,
  number =       3,
  pages =        {417--444},
  month =        sep,
  numpages =     28,
  doi =          {10.1145/1163641.1163644},
  acmid =        1163644,
}""")
    del Citations
except ImportError:
    pass
Пример #18
0
    def __init__(self,
                 m,
                 refinement_levels,
                 refinements_per_level=1,
                 reorder=None):
        """Build a hierarchy of meshes by uniformly refining a coarse mesh.

        :arg m: the coarse :func:`~.Mesh` to refine
        :arg refinement_levels: the number of levels of refinement
        :arg refinements_per_level: Optional number of refinements per
            level in the resulting hierarchy.  Note that the
            intermediate meshes are still kept, but iteration over the
            mesh hierarchy skips them.
        :arg reorder: optional flag indicating whether to reorder the
             refined meshes.
        """
        from firedrake_citations import Citations
        Citations().register("Mitchell2016")
        if m.ufl_cell().cellname() not in ["triangle", "interval"]:
            raise NotImplementedError(
                "Only supported on intervals and triangles")
        if refinements_per_level < 1:
            raise ValueError(
                "Must provide positive number of refinements per level")
        m._plex.setRefinementUniform(True)
        dm_hierarchy = []

        cdm = m._plex
        self.comm = m.comm
        fpoint_ises = []
        if m.comm.size > 1 and m._grown_halos:
            raise RuntimeError(
                "Cannot refine parallel overlapped meshes (make sure the MeshHierarchy is built immediately after the Mesh)"
            )
        for i in range(refinement_levels * refinements_per_level):
            rdm = cdm.refine()
            fpoint_ises.append(cdm.createCoarsePointIS())
            # Remove interior facet label (re-construct from
            # complement of exterior facets).  Necessary because the
            # refinement just marks points "underneath" the refined
            # facet with the appropriate label.  This works for
            # exterior, but not marked interior facets
            rdm.removeLabel("interior_facets")
            # Remove vertex (and edge) points from labels on exterior
            # facets.  Interior facets will be relabeled in Mesh
            # construction below.
            impl.filter_exterior_facet_labels(rdm)
            rdm.removeLabel("pyop2_core")
            rdm.removeLabel("pyop2_owned")
            rdm.removeLabel("pyop2_ghost")

            dm_hierarchy.append(rdm)
            cdm = rdm
            # Fix up coords if refining embedded circle or sphere
            if hasattr(m, '_radius'):
                # FIXME, really we need some CAD-like representation
                # of the boundary we're trying to conform to.  This
                # doesn't DTRT really for cubed sphere meshes (the
                # refined meshes are no longer gnonomic).
                coords = cdm.getCoordinatesLocal().array.reshape(
                    -1, m.geometric_dimension())
                scale = m._radius / np.linalg.norm(coords, axis=1).reshape(
                    -1, 1)
                coords *= scale

        hierarchy = [m] + [
            mesh.Mesh(dm,
                      dim=m.ufl_cell().geometric_dimension(),
                      distribute=False,
                      reorder=reorder) for i, dm in enumerate(dm_hierarchy)
        ]
        for m in hierarchy:
            m._non_overlapped_lgmap = impl.create_lgmap(m._plex)
            m._non_overlapped_nent = []
            for d in range(m._plex.getDimension() + 1):
                m._non_overlapped_nent.append(m._plex.getDepthStratum(d))
            m.init()
            m._overlapped_lgmap = impl.create_lgmap(m._plex)

        # On coarse mesh n, a map of consistent cell orientations and
        # vertex permutations for the fine cells on each coarse cell.
        self._cells_vperm = []

        for mc, mf, fpointis in zip(hierarchy[:-1], hierarchy[1:],
                                    fpoint_ises):
            mc._fpointIS = fpointis
            c2f = impl.coarse_to_fine_cells(mc, mf)
            P1c = functionspace.FunctionSpace(mc, 'CG', 1)
            P1f = functionspace.FunctionSpace(mf, 'CG', 1)
            self._cells_vperm.append(impl.compute_orientations(P1c, P1f, c2f))

        self._hierarchy = tuple(hierarchy[::refinements_per_level])
        self._unskipped_hierarchy = tuple(hierarchy)
        for level, m in enumerate(self):
            set_level(m, self, level)
        # Attach fractional levels to skipped parts
        # This allows us to do magic under the hood so that multigrid
        # on skipping hierarchies still works!
        for level, m in enumerate(hierarchy):
            if level % refinements_per_level == 0:
                continue
            set_level(m, self, Fraction(level, refinements_per_level))
        self.refinements_per_level = refinements_per_level