Beispiel #1
0
    def __call__(self, pc):
        from firedrake.mg.utils import get_level
        from firedrake.cython.mgimpl import get_entity_renumbering

        dmf = pc.getDM()
        ctx = pc.getAttr("ctx")

        mf = ctx._x.ufl_domain()
        (mh, level) = get_level(mf)

        coarse_to_fine_cell_map = mh.coarse_to_fine_cells[level - 1]
        (_,
         firedrake_to_plex) = get_entity_renumbering(dmf, mf._cell_numbering,
                                                     "cell")
        mc = mh[level - 1]
        (_, coarse_firedrake_to_plex) = get_entity_renumbering(
            mc._topology_dm, mc._cell_numbering, "cell")

        patches = []

        tdim = mf.topological_dimension()
        for i, fine_firedrake in enumerate(coarse_to_fine_cell_map):
            # there are d+1 many coarse cells that all map to the same fine cells.
            # We only want to build the patch once, so skip repitions
            if coarse_firedrake_to_plex[i] % (tdim + 1) != 0:
                continue
            # we need to convert firedrake cell numbering to plex cell numbering
            fine_plex = [firedrake_to_plex[ff] for ff in fine_firedrake]
            entities = []
            for fp in fine_plex:
                (pts, _) = dmf.getTransitiveClosure(fp, True)
                for pt in pts:
                    value = dmf.getLabelValue("prolongation", pt)
                    if not (value > -1 and value <= level):
                        entities.append(pt)

            iset = PETSc.IS().createGeneral(unique(entities),
                                            comm=PETSc.COMM_SELF)
            patches.append(iset)

        piterset = PETSc.IS().createStride(size=len(patches),
                                           first=0,
                                           step=1,
                                           comm=PETSc.COMM_SELF)
        return (patches, piterset)
Beispiel #2
0
    def __call__(self, pc):
        from firedrake.mg.utils import get_level
        from firedrake.cython.mgimpl import get_entity_renumbering

        dmf = pc.getDM()
        ctx = pc.getAttr("ctx")

        mf = ctx._x.ufl_domain()
        (mh, level) = get_level(mf)

        coarse_to_fine_cell_map = mh.coarse_to_fine_cells[level - 1]
        (_,
         firedrake_to_plex) = get_entity_renumbering(dmf, mf._cell_numbering,
                                                     "cell")

        patches = []
        for fine_firedrake in coarse_to_fine_cell_map:
            # we need to convert firedrake cell numbering to plex cell numbering
            fine_plex = [firedrake_to_plex[ff] for ff in fine_firedrake]
            entities = []
            for fp in fine_plex:
                (pts, _) = dmf.getTransitiveClosure(fp, True)
                for pt in pts:
                    value = dmf.getLabelValue("prolongation", pt)
                    if not (value > -1 and value <= level):
                        entities.append(pt)

            iset = PETSc.IS().createGeneral(unique(entities),
                                            comm=PETSc.COMM_SELF)
            patches.append(iset)

        piterset = PETSc.IS().createStride(size=len(patches),
                                           first=0,
                                           step=1,
                                           comm=PETSc.COMM_SELF)
        return (patches, piterset)
Beispiel #3
0
def BaryMeshHierarchy(mesh, refinement_levels, distribution_parameters=None, callbacks=None, reorder=None,
                      refinements_per_level=1):
    cdm = mesh._topology_dm
    cdm.setRefinementUniform(True)
    dms = []
    if mesh.comm.size > 1 and mesh._grown_halos:
        raise RuntimeError("Cannot refine parallel overlapped meshes "
                           "(make sure the MeshHierarchy is built immediately after the Mesh)")
    parameters = {}
    if distribution_parameters is not None:
        parameters.update(distribution_parameters)
    else:
        parameters.update(mesh._distribution_parameters)

    parameters["partition"] = False
    distribution_parameters = parameters

    if callbacks is not None:
        before, after = callbacks
    else:
        before = after = lambda dm, i: None

    for i in range(refinement_levels*refinements_per_level):
        if i % refinements_per_level == 0:
            before(cdm, i)
        rdm = cdm.refine()
        if i % refinements_per_level == 0:
            after(rdm, i)
        # 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_labels(rdm, rdm.getHeightStratum(1),
                           "exterior_facets", "boundary_faces",
                           FACE_SETS_LABEL)

        rdm.removeLabel("pyop2_core")
        rdm.removeLabel("pyop2_owned")
        rdm.removeLabel("pyop2_ghost")

        dms.append(rdm)
        cdm = rdm
        # Fix up coords if refining embedded circle or sphere
        if hasattr(mesh, '_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, mesh.geometric_dimension())
            scale = mesh._radius / np.linalg.norm(coords, axis=1).reshape(-1, 1)
            coords *= scale

    barydms = (bary(mesh._topology_dm), ) + tuple(bary(dm) for dm in dms)

    for bdm in barydms:
        impl.filter_labels(bdm, bdm.getHeightStratum(1),
                           "exterior_facets", "boundary_faces",
                           FACE_SETS_LABEL)

    barymeshes = [firedrake.Mesh(dm, dim=mesh.ufl_cell().geometric_dimension(),
                                 distribution_parameters=distribution_parameters,
                                 reorder=reorder)
                           for dm in barydms]

    meshes = [mesh] + [firedrake.Mesh(dm, dim=mesh.ufl_cell().geometric_dimension(),
                                      distribution_parameters=distribution_parameters,
                                      reorder=reorder)
                       for dm in dms]

    lgmaps = []
    for i, m in enumerate(meshes):
        no = impl.create_lgmap(m._topology_dm)
        m.init()
        o = impl.create_lgmap(m._topology_dm)
        m._topology_dm.setRefineLevel(i)
        lgmaps.append((no, o))

    coarse_to_fine_cells = []
    fine_to_coarse_cells = [None]
    for (coarse, fine), (clgmaps, flgmaps) in zip(zip(meshes[:-1], meshes[1:]),
                                                  zip(lgmaps[:-1], lgmaps[1:])):
        c2f, f2c = impl.coarse_to_fine_cells(coarse, fine, clgmaps, flgmaps)
        coarse_to_fine_cells.append(c2f)
        fine_to_coarse_cells.append(f2c)

    lgmaps = []
    for i, m in enumerate(barymeshes):
        no = impl.create_lgmap(m._topology_dm)
        m.init()
        o = impl.create_lgmap(m._topology_dm)
        m._topology_dm.setRefineLevel(i)
        lgmaps.append((no, o))

    d = mesh.topological_dimension()
    bary_coarse_to_fine_cells = []
    bary_fine_to_coarse_cells = [None]
    for (coarseu, fineu), (coarse, fine), (clgmaps, flgmaps), uniform_coarse_to_fine \
        in zip(zip(meshes[:-1], meshes[1:]),
               zip(barymeshes[:-1], barymeshes[1:]),
               zip(lgmaps[:-1], lgmaps[1:]),
               coarse_to_fine_cells):

        cdm = coarseu._topology_dm
        fdm = fineu._topology_dm
        _, cn2o = impl.get_entity_renumbering(cdm, coarseu._cell_numbering, "cell")
        _, fn2o = impl.get_entity_renumbering(fdm, fineu._cell_numbering, "cell")
        plex_uniform_coarse_to_fine = numpy.empty_like(uniform_coarse_to_fine)
        for i, cells in enumerate(uniform_coarse_to_fine):
            plexcells = fn2o[cells]
            plex_uniform_coarse_to_fine[cn2o[i], :] = plexcells

        ncoarse, nfine = plex_uniform_coarse_to_fine.shape
        plex_coarse_bary_to_fine_bary = numpy.full((ncoarse*(d+1),
                                                    nfine*(d+1)), -1, dtype=PETSc.IntType)

        for c in range(ncoarse*(d+1)):
            uniform = c // (d+1)
            fine_cells = plex_uniform_coarse_to_fine[uniform]
            bary_cells = []
            for fc in fine_cells:
                bary_cells.extend(list(range(fc*(d+1), (fc+1)*(d+1))))
            plex_coarse_bary_to_fine_bary[c] = bary_cells

        cdm = coarse._topology_dm
        fdm = fine._topology_dm

        co2n, _ = impl.get_entity_renumbering(cdm, coarse._cell_numbering, "cell")
        fo2n, _ = impl.get_entity_renumbering(fdm, fine._cell_numbering, "cell")

        coarse_bary_to_fine_bary = numpy.empty_like(plex_coarse_bary_to_fine_bary)
        # Translate plex numbering to firedrake numbering
        for i, plex_cells in enumerate(plex_coarse_bary_to_fine_bary):
            coarse_bary_to_fine_bary[co2n[i]] = fo2n[plex_cells]

        bary_coarse_to_fine_cells.append(coarse_bary_to_fine_bary)

        # Not fast but seems to work
        fine_bary_to_coarse_bary = [[]]
        for i in range(numpy.max(coarse_bary_to_fine_bary)):
            fine_bary_to_coarse_bary.append([])
        for coarse in range(coarse_bary_to_fine_bary.shape[0]):
            for ifine in range(coarse_bary_to_fine_bary.shape[1]):
                # the coarse cell `coarse` is contained in the fine cell
                # `bary_coarse_to_fine_cells[0][coarse, ifine]` so we
                # should add it to the corresponding list
                fine_bary_to_coarse_bary[coarse_bary_to_fine_bary[coarse, ifine]].append(coarse)
        fine_bary_to_coarse_bary = numpy.asarray(fine_bary_to_coarse_bary, dtype=PETSc.IntType)

        bary_fine_to_coarse_cells.append(fine_bary_to_coarse_bary)

    #print(bary_coarse_to_fine_cells)
    #print(bary_fine_to_coarse_cells)

    coarse_to_fine_cells = dict((Fraction(i, refinements_per_level), c2f)
                                for i, c2f in enumerate(bary_coarse_to_fine_cells))
    fine_to_coarse_cells = dict((Fraction(i, refinements_per_level), f2c)
                                for i, f2c in enumerate(bary_fine_to_coarse_cells))
    return HierarchyBase(barymeshes, coarse_to_fine_cells, fine_to_coarse_cells,
                         refinements_per_level, nested=False)