Пример #1
0
 def __init__(self, parameters, options_prefix):
     if parameters is None:
         parameters = {}
     else:
         parameters = parameters.copy()
     if options_prefix is None:
         self.options_prefix = "firedrake_%d_" % next(self.count)
         self.parameters = parameters
         self.to_delete = set(parameters)
     else:
         self.options_prefix = options_prefix
         # Remove those options from the dict that were passed on
         # the commandline.
         self.parameters = dict(
             (k, v) for k, v in parameters.iteritems()
             if options_prefix + k not in self.commandline_options)
         self.to_delete = set(parameters)
         # Now update parameters from options, so that they're
         # availabe to solver setup (for, e.g., matrix-free).
         for k, v in PETSc.Options(
                 self.options_prefix).getAll().iteritems():
             self.parameters[k] = v
     self.options_object = PETSc.Options(self.options_prefix)
     self._setfromoptions = False
     super(ParametersMixin, self).__init__()
Пример #2
0
    def get_patches(self, V):
        mesh = V._mesh
        mesh_dm = mesh._topology_dm

        # Obtain the topological entities to use to construct the stars
        depth = PETSc.Options().getInt(self.prefix + "construct_dim",
                                       default=-1)
        height = PETSc.Options().getInt(self.prefix + "construct_codim",
                                        default=-1)
        if (depth == -1 and height == -1) or (depth != -1 and height != -1):
            raise ValueError(
                f"Must set exactly one of {self.prefix}construct_dim or {self.prefix}construct_codim"
            )

        # Accessing .indices causes the allocation of a global array,
        # so we need to cache these for efficiency
        V_local_ises_indices = []
        for (i, W) in enumerate(V):
            V_local_ises_indices.append(V.dof_dset.local_ises[i].indices)

        # Build index sets for the patches
        ises = []
        if depth != -1:
            (start, end) = mesh_dm.getDepthStratum(depth)
        else:
            (start, end) = mesh_dm.getHeightStratum(height)

        for seed in range(start, end):
            # Only build patches over owned DoFs
            if mesh_dm.getLabelValue("pyop2_ghost", seed) != -1:
                continue

            # Create point list from mesh DM
            star, _ = mesh_dm.getTransitiveClosure(seed, useCone=False)
            pt_array = set()
            for pt in star.tolist():
                closure, _ = mesh_dm.getTransitiveClosure(seed, useCone=True)
                pt_array.update(closure.tolist())

            # Get DoF indices for patch
            indices = []
            for (i, W) in enumerate(V):
                section = W.dm.getDefaultSection()
                for p in pt_array:
                    dof = section.getDof(p)
                    if dof <= 0:
                        continue
                    off = section.getOffset(p)
                    # Local indices within W
                    W_indices = numpy.arange(off * W.value_size,
                                             W.value_size * (off + dof),
                                             dtype='int32')
                    indices.extend(V_local_ises_indices[i][W_indices])
            iset = PETSc.IS().createGeneral(indices, comm=COMM_SELF)
            ises.append(iset)

        return ises
Пример #3
0
    def initialize(self, pc):
        # Get context from pc
        _, P = pc.getOperators()
        dm = pc.getDM()
        self.prefix = pc.getOptionsPrefix() + self._prefix

        # Extract function space and mesh to obtain plex and indexing functions
        V = get_function_space(dm)

        # Obtain patches from user defined funtion
        ises = self.get_patches(V)

        # Create new PC object as ASM type and set index sets for patches
        asmpc = PETSc.PC().create(comm=pc.comm)
        asmpc.incrementTabLevel(1, parent=pc)
        asmpc.setOptionsPrefix(self.prefix + "sub_")
        asmpc.setOperators(*pc.getOperators())

        backend = PETSc.Options().getString(self.prefix + "backend",
                                            default="petscasm").lower()
        # Either use PETSc's ASM PC or use TinyASM (as simple ASM
        # implementation designed to be fast for small block sizes).
        if backend == "petscasm":
            asmpc.setType(asmpc.Type.ASM)
            # Set default solver parameters
            asmpc.setASMType(PETSc.PC.ASMType.BASIC)
            opts = PETSc.Options(asmpc.getOptionsPrefix())
            if "sub_pc_type" not in opts:
                opts["sub_pc_type"] = "lu"
            if "sub_pc_factor_shift_type" not in opts:
                opts["sub_pc_factor_shift_type"] = "NONE"
            lgmap = V.dof_dset.lgmap
            # Translate to global numbers
            ises = tuple(lgmap.applyIS(iset) for iset in ises)
            asmpc.setASMLocalSubdomains(len(ises), ises)
        elif backend == "tinyasm":
            if not have_tinyasm:
                raise ValueError(
                    "To use the TinyASM backend you need to install firedrake with TinyASM (firedrake-update --tinyasm)"
                )

            _, P = asmpc.getOperators()
            lgmap = V.dof_dset.lgmap
            P.setLGMap(rmap=lgmap, cmap=lgmap)

            asmpc.setType("tinyasm")
            # TinyASM wants local numbers, no need to translate
            tinyasm.SetASMLocalSubdomains(
                asmpc, ises, [W.dm.getDefaultSF() for W in V],
                [W.value_size for W in V],
                sum(W.value_size * W.dof_dset.total_size for W in V))
            asmpc.setUp()
        else:
            raise ValueError(f"Unknown backend type f{backend}")

        asmpc.setFromOptions()
        self.asmpc = asmpc
Пример #4
0
    def configure_pmg(self, snes, pdm):
        odm = snes.getDM()
        psnes = PETSc.SNES().create(comm=snes.comm)
        psnes.setOptionsPrefix(snes.getOptionsPrefix() + "pfas_")
        psnes.setType("fas")
        psnes.setDM(pdm)
        psnes.incrementTabLevel(1, parent=snes)

        (f, residual) = snes.getFunction()
        assert residual is not None
        (fun, args, kargs) = residual
        psnes.setFunction(fun, f.duplicate(), args=args, kargs=kargs)

        pdm.setGlobalVector(f.duplicate())
        self.dummy = f.duplicate()
        psnes.setSolution(f.duplicate())

        # PETSc unfortunately requires us to make an ugly hack.
        # We would like to use GMG for the coarse solve, at least
        # sometimes. But PETSc will use this p-DM's getRefineLevels()
        # instead of the getRefineLevels() of the MeshHierarchy to
        # decide how many levels it should use for PCMG applied to
        # the p-MG's coarse problem. So we need to set an option
        # for the user, if they haven't already; I don't know any
        # other way to get PETSc to know this at the right time.
        opts = PETSc.Options(snes.getOptionsPrefix() + "pfas_")
        if "fas_coarse_pc_mg_levels" not in opts:
            opts["fas_coarse_pc_mg_levels"] = odm.getRefineLevel() + 1
        if "fas_coarse_snes_fas_levels" not in opts:
            opts["fas_coarse_snes_fas_levels"] = odm.getRefineLevel() + 1

        return psnes
Пример #5
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
Пример #6
0
    def __call__(self, pc):
        dm = pc.getDM()
        prefix = pc.getOptionsPrefix()
        sentinel = object()
        sweeps = PETSc.Options(prefix).getString(
            "pc_patch_construct_ps_sweeps", default=sentinel)
        if sweeps == sentinel:
            raise ValueError("Must set %spc_patch_construct_ps_sweeps" %
                             prefix)

        patches = []
        for sweep in sweeps.split(':'):
            axis = int(sweep[0])
            dir = {'+': +1, '-': -1}[sweep[1]]
            ndiv = int(sweep[2:])

            entities = self.sort_entities(dm, axis, dir, ndiv)
            for patch in entities:
                iset = PETSc.IS().createGeneral(patch, comm=PETSc.COMM_SELF)
                patches.append(iset)

        iterationSet = PETSc.IS().createStride(size=len(patches),
                                               first=0,
                                               step=1,
                                               comm=PETSc.COMM_SELF)
        return (patches, iterationSet)
Пример #7
0
 def create_interpolation(self, dmc, dmf):
     prefix = dmc.getOptionsPrefix()
     mat_type = PETSc.Options(prefix).getString(
         "mg_levels_transfer_mat_type", default="matfree")
     I = self.create_transfer(get_appctx(dmc), get_appctx(dmf), mat_type,
                              True, False)
     return I, None
Пример #8
0
    def get_patches(self, V):
        mesh = V._mesh
        assert mesh.cell_set._extruded
        dm = mesh._topology_dm
        section = V.dm.getDefaultSection()
        # Obtain the codimensions to loop over from options, if present
        codim_list = PETSc.Options().getString(self.prefix + "codims", "0, 1")
        codim_list = [int(ii) for ii in codim_list.split(",")]

        # Build index sets for the patches
        ises = []
        for codim in codim_list:
            for p in range(*dm.getHeightStratum(codim)):
                # Only want to build patches over owned faces
                if dm.getLabelValue("pyop2_ghost", p) != -1:
                    continue
                dof = section.getDof(p)
                if dof <= 0:
                    continue
                off = section.getOffset(p)
                indices = numpy.arange(off * V.value_size,
                                       V.value_size * (off + dof),
                                       dtype='int32')
                iset = PETSc.IS().createGeneral(indices, comm=COMM_SELF)
                ises.append(iset)

        return ises
Пример #9
0
 def create_injection(self, dmc, dmf):
     prefix = dmc.getOptionsPrefix()
     mat_type = PETSc.Options(prefix).getString(
         "mg_levels_transfer_mat_type", default="matfree")
     I = self.create_transfer(get_appctx(dmf), get_appctx(dmc), mat_type,
                              False, False)
     return PETSc.Mat().createTranspose(I)
Пример #10
0
    def __call__(self, pc):
        dm = pc.getDM()
        prefix = pc.getOptionsPrefix()
        opts = PETSc.Options(prefix)

        select = partial(self.select_entity, dm=dm, exclude="pyop2_ghost")
        (pStart, pEnd) = dm.getChart()
        owned_entities = set(filter(select, range(pStart, pEnd)))

        overlap = 1  # FIXME: get from options
        all_entities = set(owned_entities)
        for i in range(overlap):
            tmp_entities = set(all_entities)
            for entity in tmp_entities:
                for s in self.star(dm, entity):
                    for c in self.closure(dm, s):
                        all_entities.add(c)

        overlap_entities = list(all_entities.difference(owned_entities))

        iset = PETSc.IS().createGeneral(overlap_entities, comm=PETSc.COMM_SELF)
        patches = [iset]
        iterset = PETSc.IS().createStride(size=len(patches),
                                          first=0,
                                          step=1,
                                          comm=PETSc.COMM_SELF)

        #print("owned_entities: ", owned_entities)
        #print("all_entities: ", all_entities)
        #print("overlap_entities: ", overlap_entities)
        return (patches, iterset)
Пример #11
0
 def __del__(self):
     # Remove stuff from the options database
     # It's fixed size, so if we don't it gets too big.
     if self._auto_prefix and hasattr(self, '_opt_prefix'):
         opts = PETSc.Options()
         for k in self.parameters.iterkeys():
             del opts[self._opt_prefix + k]
         delattr(self, '_opt_prefix')
Пример #12
0
 def _check_options(self, valid):
     default = object()
     opts = PETSc.Options(self.prefix)
     for key, supported in valid:
         value = opts.getString(key, default=default)
         if value is not default and value not in supported:
             raise ValueError(
                 f"Unsupported value ({value}) for '{self.prefix + key}'. "
                 f"Should be one of {supported}")
def test_petsc_options_cleared(a_L_out):
    a, L, out = a_L_out
    opts = PETSc.Options()
    original = {}
    original.update(opts.getAll())

    solve(a == L, out, solver_parameters={'foo': 'bar'})

    assert original == opts.getAll()
Пример #14
0
    def initialize(self, pc):
        # Make a new DM.
        # Hook up a (new) coarsen routine on that DM.
        # Make a new PC, of type MG.
        # Assign the DM to that PC.

        odm = pc.getDM()
        ctx = get_appctx(odm)

        test, trial = ctx.J.arguments()
        if test.function_space() != trial.function_space():
            raise NotImplementedError("test and trial spaces must be the same")

        prefix = pc.getOptionsPrefix()
        options_prefix = prefix + "pmg_"
        pdm = PETSc.DMShell().create(comm=pc.comm)
        pdm.setOptionsPrefix(options_prefix)

        # Get the coarse degree from PETSc options
        self.coarse_degree = PETSc.Options(options_prefix).getInt("mg_coarse_degree", default=1)

        # Construct a list with the elements we'll be using
        V = test.function_space()
        ele = V.ufl_element()
        elements = [ele]
        while True:
            try:
                ele_ = self.coarsen_element(ele)
                assert ele_.value_shape() == ele.value_shape()
                ele = ele_
            except ValueError:
                break
            elements.append(ele)

        sf = odm.getPointSF()
        section = odm.getDefaultSection()
        attach_hooks(pdm, level=len(elements)-1, sf=sf, section=section)
        # Now overwrite some routines on the DM
        pdm.setRefine(None)
        pdm.setCoarsen(self.coarsen)
        pdm.setCreateInterpolation(self.create_interpolation)
        # We need this for p-FAS
        pdm.setCreateInjection(self.create_injection)
        pdm.setSNESJacobian(_SNESContext.form_jacobian)
        pdm.setSNESFunction(_SNESContext.form_function)
        pdm.setKSPComputeOperators(_SNESContext.compute_operators)

        set_function_space(pdm, get_function_space(odm))

        parent = get_parent(odm)
        assert parent is not None
        add_hook(parent, setup=partial(push_parent, pdm, parent), teardown=partial(pop_parent, pdm, parent), call_setup=True)
        add_hook(parent, setup=partial(push_appctx, pdm, ctx), teardown=partial(pop_appctx, pdm, ctx), call_setup=True)

        self.ppc = self.configure_pmg(pc, pdm)
        self.ppc.setFromOptions()
        self.ppc.setUp()
Пример #15
0
    def __init__(self, Q, free_bids=["on_boundary"]):
        (V, I_interp) = Q.get_space_for_inner()

        self.free_bids = free_bids

        u = fd.TrialFunction(V)
        v = fd.TestFunction(V)

        n = fd.FacetNormal(V.mesh())

        def surf_grad(u):
            return fd.sym(fd.grad(u) - fd.outer(fd.grad(u) * n, n))

        a = (fd.inner(surf_grad(u), surf_grad(v)) + fd.inner(u, v)) * fd.ds
        # petsc doesn't like matrices with zero rows
        a += 1e-10 * fd.inner(u, v) * fd.dx
        A = fd.assemble(a, mat_type="aij")
        A = A.petscmat
        tdim = V.mesh().topological_dimension()

        lsize = fd.Function(V).vector().local_size()

        def get_nodes_bc(bc):
            nodes = bc.nodes
            return nodes[nodes < lsize]

        def get_nodes_bid(bid):
            bc = fd.DirichletBC(V, fd.Constant(tdim * (0, )), bid)
            return get_nodes_bc(bc)

        free_nodes = np.concatenate(
            [get_nodes_bid(bid) for bid in self.free_bids])
        free_dofs = np.concatenate(
            [tdim * free_nodes + i for i in range(tdim)])
        free_dofs = np.unique(np.sort(free_dofs))
        self.free_is = PETSc.IS().createGeneral(free_dofs)
        lgr, lgc = A.getLGMap()
        self.global_free_is_row = lgr.applyIS(self.free_is)
        self.global_free_is_col = lgc.applyIS(self.free_is)
        A = A.createSubMatrix(self.global_free_is_row, self.global_free_is_col)
        # A.view()
        A.assemble()
        self.A = A
        Aksp = PETSc.KSP().create()
        Aksp.setOperators(self.A)
        Aksp.setOptionsPrefix("A_")
        opts = PETSc.Options()
        opts["A_ksp_type"] = "cg"
        opts["A_pc_type"] = "hypre"
        opts["A_ksp_atol"] = 1e-10
        opts["A_ksp_rtol"] = 1e-10
        Aksp.setUp()
        Aksp.setFromOptions()
        self.Aksp = Aksp
def opts(request, prefix, global_parameters):
    opts = PETSc.Options()
    if prefix is None:
        prefix = ""

    for k, v in global_parameters.iteritems():
        opts["%s%s" % (prefix, k)] = v

    def finalize():
        for k in global_parameters.keys():
            del opts["%s%s" % (prefix, k)]

    request.addfinalizer(finalize)
Пример #17
0
    def user_construction_op(self, obj, *args, **kwargs):
        prefix = obj.getOptionsPrefix()
        sentinel = object()
        usercode = PETSc.Options(prefix).getString("%s_patch_construct_python_type" % self._objectname, default=sentinel)
        if usercode == sentinel:
            raise ValueError("Must set %s%s_patch_construct_python_type" % (prefix, self._objectname))

        (modname, funname) = usercode.rsplit('.', 1)
        mod = __import__(modname)
        fun = getattr(mod, funname)
        if isinstance(fun, type):
            fun = fun()
        return fun(obj, *args, **kwargs)
Пример #18
0
    def initialize(self, pc):
        from firedrake import TrialFunction, TestFunction, dx, assemble, inner, parameters
        if pc.getType() != "python":
            raise ValueError("Expecting PC type python")
        prefix = pc.getOptionsPrefix()
        options_prefix = prefix + "Mp_"
        # we assume P has things stuffed inside of it
        _, P = pc.getOperators()
        context = P.getPythonContext()

        test, trial = context.a.arguments()

        if test.function_space() != trial.function_space():
            raise ValueError(
                "MassInvPC only makes sense if test and trial space are the same"
            )

        V = test.function_space()

        mu = context.appctx.get("mu", 1.0)

        u = TrialFunction(V)
        v = TestFunction(V)
        # Handle vector and tensor-valued spaces.

        # 1/mu goes into the inner product in case it varies spatially.
        a = inner(1 / mu * u, v) * dx

        opts = PETSc.Options()
        mat_type = opts.getString(options_prefix + "mat_type",
                                  parameters["default_matrix_type"])

        A = assemble(a,
                     form_compiler_parameters=context.fc_params,
                     mat_type=mat_type,
                     options_prefix=options_prefix)
        A.force_evaluation()

        Pmat = A.petscmat
        Pmat.setNullSpace(P.getNullSpace())
        tnullsp = P.getTransposeNullSpace()
        if tnullsp.handle != 0:
            Pmat.setTransposeNullSpace(tnullsp)

        ksp = PETSc.KSP().create(comm=pc.comm)
        ksp.incrementTabLevel(1, parent=pc)
        ksp.setOperators(Pmat)
        ksp.setOptionsPrefix(options_prefix)
        ksp.setFromOptions()
        ksp.setUp()
        self.ksp = ksp
Пример #19
0
    def initialize(self, pc):
        from firedrake.assemble import allocate_matrix, create_assembly_callable

        _, P = pc.getOperators()

        if pc.getType() != "python":
            raise ValueError("Expecting PC type python")
        opc = pc
        context = P.getPythonContext()
        prefix = pc.getOptionsPrefix()
        options_prefix = prefix + "assembled_"

        # It only makes sense to preconditioner/invert a diagonal
        # block in general.  That's all we're going to allow.
        if not context.on_diag:
            raise ValueError("Only makes sense to invert diagonal block")

        mat_type = PETSc.Options().getString(options_prefix + "mat_type",
                                             "aij")
        self.P = allocate_matrix(context.a,
                                 bcs=context.row_bcs,
                                 form_compiler_parameters=context.fc_params,
                                 mat_type=mat_type,
                                 options_prefix=options_prefix)
        self._assemble_P = create_assembly_callable(
            context.a,
            tensor=self.P,
            bcs=context.row_bcs,
            form_compiler_parameters=context.fc_params,
            mat_type=mat_type)
        self._assemble_P()
        self.P.force_evaluation()

        # Transfer nullspace over
        Pmat = self.P.petscmat
        Pmat.setNullSpace(P.getNullSpace())
        tnullsp = P.getTransposeNullSpace()
        if tnullsp.handle != 0:
            Pmat.setTransposeNullSpace(tnullsp)

        # Internally, we just set up a PC object that the user can configure
        # however from the PETSc command line.  Since PC allows the user to specify
        # a KSP, we can do iterative by -assembled_pc_type ksp.
        pc = PETSc.PC().create(comm=opc.comm)
        pc.incrementTabLevel(1, parent=opc)
        pc.setOptionsPrefix(options_prefix)
        pc.setOperators(Pmat, Pmat)
        pc.setFromOptions()
        pc.setUp()
        self.pc = pc
def GetPETScBFBTApproximateToSchurInverse():

    Fass = assemble(lhs(F))
    Gass = assemble(inner(u, v) * dx)
    # bcin.apply(Fass)
    # bcnoslip.apply(Fass)
    # bcin.apply(Gass)
    # bcnoslip.apply(Gass)
    A = Fass.M[0,0].handle
    BT = Fass.M[0,1].handle
    B = Fass.M[1,0].handle
    D = Fass.M[1,1].handle
    VM = Gass.M[0, 0].handle
    # Adiag = A.getDiagonal()
    Adiag = VM.getRowSum()
    invAdiag = Adiag.duplicate()
    Adiag.copy(invAdiag)
    invAdiag.reciprocal()

    Einv = A.duplicate()
    Einv.setDiagonal(invAdiag)
    # Einv.convert(PETSc.Mat.Type.SEQAIJ)
    BEBT = B.matMult(Einv.matMult(BT))

    BEBT_ksp = PETSc.KSP().create()
    BEBT_ksp.setOperators(BEBT)
    opts = PETSc.Options()
    BEBT_ksp.setOptionsPrefix("bebt_")
    opts['bebt_ksp_type'] = 'richardson'
    opts['bebt_pc_type'] = 'hypre'
    opts['bebt_ksp_max_it'] = 1
    opts['bebt_ksp_atol'] = 1.0e-9
    opts['bebt_ksp_rtol'] = 1.0e-9
    BEBT_ksp.setUp()
    BEBT_ksp.setFromOptions()

    MIDDLE = B.matMult(Einv.matMult(A.matMult(Einv.matMult(BT)))) 
    MIDDLE.scale(-1)
    class SchurInvApprox(object):
        def mult(self, mat, x, y):
            y1 = y.duplicate()
            BEBT_ksp.solve(x, y1)
            y2 = y.duplicate()
            MIDDLE.mult(y1, y2)
            BEBT_ksp.solve(y2, y)

    schur = PETSc.Mat()
    schur.createPython(D.getSizes(), SchurInvApprox())
    schur.setUp()
    return schur
Пример #21
0
    def __call__(self, pc):
        dm = pc.getDM()
        prefix = pc.getOptionsPrefix()
        sentinel = object()
        opts = PETSc.Options(prefix)
        name = self.name
        assert self.name is not None

        self.set_options(dm, opts, name)

        select = partial(select_entity, dm=dm, exclude="pyop2_ghost")
        entities = list(filter(select, self.get_entities(opts, name, dm)))

        nclosure = opts.getInt("pc_patch_construction_%s_nclosures" % name, default=1)
        patches = []
        for entity in entities:
            subentities = self.callback(dm, entity, nclosure)
            iset = PETSc.IS().createGeneral(subentities, comm=PETSc.COMM_SELF)
            patches.append(iset)

        # Now make the iteration set.
        iterset = []

        sortorders = opts.getString("pc_patch_construction_%s_sort_order" % name, default=sentinel)
        if sortorders == sentinel:
            sortorders = "None"

        if sortorders == "None":
            piterset = PETSc.IS().createStride(size=len(patches), first=0, step=1, comm=PETSc.COMM_SELF)
            return (patches, piterset)

        coords = list(enumerate(self.coords(dm, p) for p in entities))
        for sortorder in sortorders.split("|"):
            sortdata = []
            for axis in sortorder.split(':'):
                ax = int(axis[0])
                if len(axis) > 1:
                    sgn = {'+': 1, '-': -1}[axis[1]]
                else:
                    sgn = 1
                sortdata.append((ax, sgn))

            def keyfunc(z):
                return tuple(sgn*z[1][ax] for (ax, sgn) in sortdata)

            iterset += [x[0] for x in sorted(coords, key=keyfunc)]

        piterset = PETSc.IS().createGeneral(iterset, comm=PETSc.COMM_SELF)
        return (patches, piterset)
Пример #22
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
Пример #23
0
def opts(request, prefix, global_parameters):
    opts = PETSc.Options()
    if prefix is None:
        prefix = ""

    for k, v in global_parameters.items():
        opts[prefix + k] = v

    # Pretend these came from the commandline
    OptionsManager.commandline_options = frozenset(opts.getAll())

    def finalize():
        for k in global_parameters.keys():
            del opts[prefix + k]
        # And remove again
        OptionsManager.commandline_options = frozenset(opts.getAll())

    request.addfinalizer(finalize)
Пример #24
0
def update_parameters(obj, petsc_obj):
    """Update parameters on a petsc object

    :arg obj: An object with a parameters dict (mapping to petsc options).
    :arg petsc_obj: The PETSc object to set parameters on."""
    # Skip if parameters haven't changed
    if hasattr(obj,
               '_set_parameters') and obj.parameters == obj._set_parameters:
        return
    opts = PETSc.Options(obj._opt_prefix)
    for k, v in obj.parameters.iteritems():
        if type(v) is bool:
            if v:
                opts[k] = None
        else:
            opts[k] = v
    petsc_obj.setFromOptions()
    obj._set_parameters = obj.parameters.copy()
Пример #25
0
def solve(ctx, state):
    out_file = File(solution_out) if solution_out else None

    mass = state["mass"]
    hats = state["hats"]

    u = ctx[2]["u"]
    u0 = ctx[2]["u0"]
    solver = ctx[1]

    from firedrake.petsc import PETSc
    ksp_hats = PETSc.KSP()
    ksp_hats.create()
    ksp_hats.setOperators(hats)
    opts = PETSc.Options()

    opts['ksp_type'] = inner_ksp
    opts['ksp_max_it'] = max_iterations
    opts['pc_type'] = 'hypre'
    ksp_hats.setFromOptions()

    class SchurInv(object):
        def mult(self, mat, x, y):
            tmp1 = y.duplicate()
            tmp2 = y.duplicate()
            ksp_hats.solve(x, tmp1)
            mass.mult(tmp1, tmp2)
            ksp_hats.solve(tmp2, y)

    pc_schur = PETSc.Mat()
    pc_schur.createPython(mass.getSizes(), SchurInv())
    pc_schur.setUp()
    pc = solver.snes.ksp.pc
    pc.setFieldSplitSchurPreType(PETSc.PC.SchurPreType.USER, pc_schur)

    for step in range(steps):
        casper.invoke_task(ctx, "assign", state)
        solver.solve()
        if out_file is not None:
            out_file.write(u.split()[0], time=step)
        if compute_norms:
            nu = norm(u)
            if comm.rank == 0:
                print(step, 'L2(u):', nu)
Пример #26
0
    def get_patches(self, V):
        mesh = V._mesh
        mesh_dm = mesh.topology_dm
        if mesh.layers:
            warning("applying ASMStarPC on an extruded mesh")

        # Obtain the topological entities to use to construct the stars
        depth = PETSc.Options().getInt(self.prefix+"construct_dim", default=0)

        # Accessing .indices causes the allocation of a global array,
        # so we need to cache these for efficiency
        V_local_ises_indices = []
        for (i, W) in enumerate(V):
            V_local_ises_indices.append(V.dof_dset.local_ises[i].indices)

        # Build index sets for the patches
        ises = []
        (start, end) = mesh_dm.getDepthStratum(depth)
        for seed in range(start, end):
            # Only build patches over owned DoFs
            if mesh_dm.getLabelValue("pyop2_ghost", seed) != -1:
                continue

            # Create point list from mesh DM
            pt_array, _ = mesh_dm.getTransitiveClosure(seed, useCone=False)

            # Get DoF indices for patch
            indices = []
            for (i, W) in enumerate(V):
                section = W.dm.getDefaultSection()
                for p in pt_array.tolist():
                    dof = section.getDof(p)
                    if dof <= 0:
                        continue
                    off = section.getOffset(p)
                    # Local indices within W
                    W_indices = numpy.arange(off*W.value_size, W.value_size * (off + dof), dtype=IntType)
                    indices.extend(V_local_ises_indices[i][W_indices])
            iset = PETSc.IS().createGeneral(indices, comm=COMM_SELF)
            ises.append(iset)

        return ises
Пример #27
0
def test_options_database_cleared():
    opts = PETSc.Options()
    expect = len(opts.getAll())

    mesh = UnitIntervalMesh(1)
    V = FunctionSpace(mesh, "DG", 0)
    u = TrialFunction(V)
    v = TestFunction(V)
    A = assemble(inner(u, v) * dx)
    b = assemble(conj(v) * dx)
    u = Function(V)
    solvers = []
    for i in range(100):
        solver = LinearSolver(A,
                              solver_parameters={
                                  "ksp_type": "preonly",
                                  "pc_type": "lu"
                              })
        solver.solve(u, b)
        solvers.append(solver)
    assert expect == len(opts.getAll())
Пример #28
0
    def assembleK(self):
        ctx = self.ctx
        mat_type = PETSc.Options().getString(
            self.prefix + "assembled_mat_type", "aij")

        self.K = allocate_matrix(ctx.a,
                                 bcs=ctx.row_bcs,
                                 form_compiler_parameters=ctx.fc_params,
                                 mat_type=mat_type)

        self._assemble_K = create_assembly_callable(
            ctx.a,
            tensor=self.K,
            bcs=ctx.row_bcs,
            form_compiler_parameters=ctx.fc_params,
            mat_type=mat_type)
        self._assemble_K()

        self.mat_type = mat_type

        self.K.force_evaluation()
Пример #29
0
    def _retrieve_options(self, pc):
        get_option = lambda key: PETSc.Options(self.prefix).getString(
            key, default="")

        # Get options for Schur complement decomposition
        self._check_options([("ksp_type", {"preonly"}),
                             ("pc_type", {"fieldsplit"}),
                             ("pc_fieldsplit_type", {"schur"})])
        self.nested = (get_option("ksp_type") == "preonly"
                       and get_option("pc_type") == "fieldsplit"
                       and get_option("pc_fieldsplit_type") == "schur")

        # Get preconditioning options for A00
        fs0, fs1 = ("fieldsplit_" + str(idx) for idx in (self.vidx, self.pidx))
        self._check_options([(fs0 + "ksp_type", {"preonly", "default"}),
                             (fs0 + "pc_type", {"jacobi"})])
        self.preonly_A00 = get_option(fs0 + "_ksp_type") == "preonly"
        self.jacobi_A00 = get_option(fs0 + "_pc_type") == "jacobi"

        # Get preconditioning options for the Schur complement
        self._check_options([(fs1 + "ksp_type", {"preonly", "default"}),
                             (fs1 + "pc_type", {"jacobi", "python"})])
        self.preonly_S = get_option(fs1 + "_ksp_type") == "preonly"
        self.jacobi_S = get_option(fs1 + "_pc_type") == "jacobi"

        # Get user supplied operator and its options
        self.schur_approx = (self.retrieve_user_S_approx(
            pc, get_option(fs1 + "_pc_python_type"))
                             if get_option(fs1 +
                                           "_pc_type") == "python" else None)
        self._check_options([(fs1 + "aux_ksp_type", {"preonly", "default"}),
                             (fs1 + "aux_pc_type", {"jacobi"})])
        self.preonly_Shat = get_option(fs1 + "_aux_ksp_type") == "preonly"
        self.jacobi_Shat = get_option(fs1 + "_aux_pc_type") == "jacobi"

        if self.jacobi_Shat or self.jacobi_A00:
            assert parameters["slate_compiler"]["optimise"], (
                "Local systems should only get preconditioned with "
                "a preconditioning matrix if the Slate optimiser replaces "
                "inverses by solves.")
Пример #30
0
    def transfer_manager(self):
        """This allows the transfer manager to be set from options, e.g.

        solver_parameters = {"ksp_type": "cg",
                             "pc_type": "mg",
                             "mg_transfer_manager": __name__ + ".manager"}

        The value for "mg_transfer_manager" can either be a specific instantiated
        object, or a function or class name. In the latter case it will be invoked
        with no arguments to instantiate the object.

        If "snes_type": "fas" is used, the relevant option is "fas_transfer_manager",
        with the same semantics.
        """
        if self._transfer_manager is None:
            opts = PETSc.Options()
            prefix = self.options_prefix or ""
            if opts.hasName(prefix + "mg_transfer_manager"):
                managername = opts[prefix + "mg_transfer_manager"]
            elif opts.hasName(prefix + "fas_transfer_manager"):
                managername = opts[prefix + "fas_transfer_manager"]
            else:
                managername = None

            if managername is None:
                from firedrake import TransferManager

                transfer = TransferManager(use_averaging=True)
            else:
                (modname, objname) = managername.rsplit(".", 1)
                mod = __import__(modname)
                obj = getattr(mod, objname)
                if isinstance(obj, type):
                    transfer = obj()
                else:
                    transfer = obj

            self._transfer_manager = transfer
        return self._transfer_manager